Hobbyelektronik.org hobbye_dbmw20 https://hobbyelektronik.org/w/index.php/Hauptseite MediaWiki 1.34.1 first-letter Medium Spezial Diskussion Benutzer Benutzer Diskussion Hobbyelektronik.org Hobbyelektronik.org Diskussion Datei Datei Diskussion MediaWiki MediaWiki Diskussion Vorlage Vorlage Diskussion Hilfe Hilfe Diskussion Kategorie Kategorie Diskussion Gadget Gadget Diskussion Gadget-Definition Gadget-Definition Diskussion FAQ FAQ talk Testseite 0 2 2 2007-08-16T10:21:53Z Chris 2 Die Seite wurde neu angelegt: Testseite, für interne Verwendung. wikitext text/x-wiki Testseite, für interne Verwendung. 08adc4eef0ed02723a0fd2156ef0a22ca22b1f89 16 2 2007-10-01T21:14:22Z Qsysopr 1 wikitext text/x-wiki Testseite, für interne Verwendung. [[Category:Elektronik]] 9f24d3eed578eae7439d814e80a6c52b497705d2 Diskussion:Testseite 1 3 3 2007-08-16T10:22:07Z Chris 2 Die Seite wurde neu angelegt: Die Diskussion ist eröffnet wikitext text/x-wiki Die Diskussion ist eröffnet 11bdfbc2e7aa2d2ce7a645ceb76484661fe209f2 Hobbyelektronik.org:Impressum 4 4 4 2007-08-17T21:42:14Z Chris 2 Die Seite wurde neu angelegt: == Hauptverantwortlicher<br> == [[Benutzer:Chris|Christof Rueß]]<br>St.-Wendelin-Str. 9<br>89264 Weißenhorn<br>E-Mail: chris at hobbyelektronik punkt org<br>ICQ: [[I... wikitext text/x-wiki == Hauptverantwortlicher<br> == [[Benutzer:Chris|Christof Rueß]]<br>St.-Wendelin-Str. 9<br>89264 Weißenhorn<br>E-Mail: chris at hobbyelektronik punkt org<br>ICQ: [[Image:Http://web.icq.com/whitepages/online?icq=78202589&img=5]] [http://www.icq.com/people/about_me.php?uin=176979879 176979879] == Mitwirkende == [[Benutzer:Robert|Robert Obermayer]]<br>E-Mail: robert at hobbyelektronik punkt org<br>ICQ: [[Image:Http://web.icq.com/whitepages/online?icq=78202589&img=5]] [http://www.icq.com/people/about_me.php?uin=176979879 78202589] == Kontakt == Wenn du Fragen an uns hast, lies bitte zuerst nochmal die Seite, zu der du die Frage hast und dann evtl. nochmal die [[Kategorie:FAQ|FAQ]].<br>Am einfachsten und am unkompliziertesten ist der Kontakt per E-Mail.<br>Um Spams ein bisschen einzuschränken, dürftest du auf der Homepage hier keine klickbaren Links finden. Wie man an die Adresse kommt, muss (so denke ich) nicht erklärt werden. Bitte beachte auch die Seite [[Hobbyelektronik.org:Über_Hobbyelektronik.org|Über Hobbyelektronik.org]], auf der insbesondere der Haftungsausschluss zu beachten ist! 9beca6c3273e590cc3ff5f68d726bfd08008fd89 5 4 2007-08-17T21:42:47Z Chris 2 wikitext text/x-wiki == Hauptverantwortlicher<br> == [[Benutzer:Chris|Christof Rueß]]<br>St.-Wendelin-Str. 9<br>89264 Weißenhorn<br>E-Mail: chris at hobbyelektronik punkt org<br>ICQ: [[http://web.icq.com/whitepages/online?icq=78202589&img=5]] [http://www.icq.com/people/about_me.php?uin=176979879 176979879] == Mitwirkende == [[Benutzer:Robert|Robert Obermayer]]<br>E-Mail: robert at hobbyelektronik punkt org<br>ICQ: [[http://web.icq.com/whitepages/online?icq=78202589&img=5]] [http://www.icq.com/people/about_me.php?uin=176979879 78202589] == Kontakt == Wenn du Fragen an uns hast, lies bitte zuerst nochmal die Seite, zu der du die Frage hast und dann evtl. nochmal die.<br>Am einfachsten und am unkompliziertesten ist der Kontakt per E-Mail.<br>Um Spams ein bisschen einzuschränken, dürftest du auf der Homepage hier keine klickbaren Links finden. Wie man an die Adresse kommt, muss (so denke ich) nicht erklärt werden. <br> Bitte beachte auch die Seite [[Hobbyelektronik.org:Über Hobbyelektronik.org|Über Hobbyelektronik.org]], auf der insbesondere der Haftungsausschluss zu beachten ist! [[Category:FAQ]] 3070adfc83d394004082604c26c37c75cda47463 6 5 2007-08-17T21:45:50Z Chris 2 wikitext text/x-wiki == Hauptverantwortlicher<br> == [[Benutzer:Chris|Christof Rueß]]<br>St.-Wendelin-Str. 9<br>89264 Weißenhorn<br>E-Mail: chris at hobbyelektronik punkt org<br>ICQ: http://web.icq.com/whitepages/online?icq=78202589&img=5 [[http://www.icq.com/people/about_me.php?uin=176979879] 176979879] == Mitwirkende == [[Benutzer:Robert|Robert Obermayer]]<br>E-Mail: robert at hobbyelektronik punkt org<br>ICQ: http://web.icq.com/whitepages/online?icq=78202589&img=5 [http://www.icq.com/people/about_me.php?uin=176979879 78202589] == Kontakt == Wenn du Fragen an uns hast, lies bitte zuerst nochmal die Seite, zu der du die Frage hast und dann evtl. nochmal die.<br>Am einfachsten und am unkompliziertesten ist der Kontakt per E-Mail.<br>Um Spams ein bisschen einzuschränken, dürftest du auf der Homepage hier keine klickbaren Links finden. Wie man an die Adresse kommt, muss (so denke ich) nicht erklärt werden. <br> Bitte beachte auch die Seite [[Hobbyelektronik.org:Über Hobbyelektronik.org|Über Hobbyelektronik.org]], auf der insbesondere der Haftungsausschluss zu beachten ist! [[Category:FAQ]] d819e6f2b8b9b4f03a59a30e2c7ae9105815e6eb 7 6 2007-08-17T21:48:16Z Chris 2 wikitext text/x-wiki == Hauptverantwortlicher<br> == [[Benutzer:Chris|Christof Rueß]]<br>St.-Wendelin-Str. 9<br>89264 Weißenhorn<br>E-Mail: chris at hobbyelektronik punkt org<br>ICQ: [http://www.icq.com/people/about_me.php?uin=176979879 176979879] == Mitwirkende == [[Benutzer:Robert|Robert Obermayer]]<br>E-Mail: robert at hobbyelektronik punkt org<br>ICQ: [http://www.icq.com/people/about_me.php?uin=176979879 78202589] == Kontakt == Wenn du Fragen an uns hast, lies bitte zuerst nochmal die Seite, zu der du die Frage hast und dann evtl. nochmal die [[FAQ]].<br>Am einfachsten und am unkompliziertesten ist der Kontakt per E-Mail.<br>Um Spams ein bisschen einzuschränken, dürftest du auf der Homepage hier keine klickbaren Links finden. Wie man an die Adresse kommt, muss (so denke ich) nicht erklärt werden. <br> Bitte beachte auch die Seite [[Hobbyelektronik.org:Über Hobbyelektronik.org|Über Hobbyelektronik.org]], auf der insbesondere der Haftungsausschluss zu beachten ist! 9868854ba72d0a9b085d73a3b4eb583a563b815f 8 7 2007-08-17T21:54:05Z Chris 2 wikitext text/x-wiki == Hauptverantwortlicher<br> == [[Benutzer:Chris|Christof Rueß]]<br>St.-Wendelin-Str. 9<br>89264 Weißenhorn<br>E-Mail: chris at hobbyelektronik punkt org<br>ICQ: [http://www.icq.com/people/about_me.php?uin=176979879 176979879] == Mitwirkende == [[Benutzer:Robert|Robert Obermayer]]<br>E-Mail: robert at hobbyelektronik punkt org<br>ICQ: [http://www.icq.com/people/about_me.php?uin=176979879 78202589] == Kontakt == Wenn du Fragen an uns hast, lies bitte zuerst nochmal die Seite, zu der du die Frage hast und dann evtl. nochmal die [[FAQ]].<br>Am einfachsten und am unkompliziertesten ist der Kontakt per E-Mail.<br>Um Spams ein bisschen einzuschränken, dürftest du auf der Homepage hier keine klickbaren Links finden. Wie man an die Adresse kommt, muss (so denke ich) nicht erklärt werden. Weiterhin habe wir einen [[#hobbyelektronik|IRC-Channel]], der von uns auch relativ stark genutzt wird und auch internationales Publikum (ok, ein Schwede) hat. Einfach mal vorbeischauen: [irc://irc.quakenet.eu.org/hobbyelektronik #hobbyelektronik @ Quakenet] <br> Bitte beachte auch die Seite [[Hobbyelektronik.org:Über Hobbyelektronik.org|Über Hobbyelektronik.org]], auf der insbesondere der Haftungsausschluss zu beachten ist! 4b314f73cda7da9fb759eb5c15e32b6f48a95881 Hauptseite 0 1 11 2007-09-17T20:49:30Z Chris 2 Erste Version der Startseite wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. 3dc406e8fa4fbe64b8d09446e70de3d89617f974 Hobbyelektronik.org:Datenschutz 4 6 12 2007-09-18T19:49:01Z Chris 2 Die Seite wurde neu angelegt: Datenschutz ist uns wichtig. Deshalb werden hier von Besuchern so wenig Daten wie möglich gespeichert.<br>Außer den Informationen, die MediaWiki sammelt, werden vom H... wikitext text/x-wiki Datenschutz ist uns wichtig. Deshalb werden hier von Besuchern so wenig Daten wie möglich gespeichert.<br>Außer den Informationen, die MediaWiki sammelt, werden vom Hoster standardmäßig Logs geschrieben. Diese Daten werden jedoch vertraulich behandelt und nicht an Dritte weitergegeben. Niemand wird dazu gezwungen, private Daten oder sonstige Informationen an uns weiterzugeben. Gleiches gilt für die Diskussionsseiten. Wenn du nicht möchtest, dass deine IP dort veröffentlicht wird, schicke uns eine [[Hobbyelektronik.org:Impressum|E-Mail]] mit deinem Kommentar. Wir werden es dann bei Gelegenheit einfügen. db2279b711f4d9dc140a4557e8abe7abdecda85d MediaWiki:Sidebar 8 8 14 2007-10-01T20:54:31Z Qsysopr 1 Die Seite wurde neu angelegt: * navigation ** mainpage|mainpage ** portal-url|portal ** currentevents-url|currentevents ** recentchanges-url|recentchanges ** randompage-url|randompage * Bereiche **... wikitext text/x-wiki * navigation ** mainpage|mainpage ** portal-url|portal ** currentevents-url|currentevents ** recentchanges-url|recentchanges ** randompage-url|randompage * Bereiche ** Elektronik (ohne µC) ** AVR ** am PC ** Software (PC) ** LCDs ** Maschinen ** Sonstiges ** Murks 70dae83e100ffd15ba818c217daf240f65ef024c 15 14 2007-10-01T20:56:52Z Qsysopr 1 wikitext text/x-wiki * navigation ** mainpage|mainpage ** portal-url|portal ** currentevents-url|currentevents ** recentchanges-url|recentchanges ** randompage-url|randompage * Bereiche ** Category:Elektronik|Elektronik (ohne µC) ** Category:AVR|AVR ** Category:PC|am PC ** Category:Software|Software (PC) ** Category:LCD|LCDs ** Category:Maschinen|Maschinen ** Category:Sonstiges|Sonstiges ** Category:Murks|Murks f867d144b5ad7a1b27967a58f4b66578d10edb36 Datei:Nixie-Aufbau.gif 6 9 17 2007-10-02T21:49:53Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-beta.jpg 6 10 18 2007-10-02T21:50:08Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Dimm-alt.jpg 6 11 19 2007-10-02T21:50:24Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Dimm-brd.gif 6 12 20 2007-10-02T21:50:40Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Dimm-sch.gif 6 13 21 2007-10-02T21:50:53Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-fertig.jpg 6 14 22 2007-10-02T21:51:08Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Glimmdef.jpg 6 15 23 2007-10-02T21:51:41Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Logik-auf-oben.jpg 6 16 24 2007-10-02T21:51:59Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Logik-auf-unten.jpg 6 17 26 2007-10-03T16:55:50Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Logik-brd.gif 6 18 27 2007-10-03T16:56:14Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Logik-sch.gif 6 19 28 2007-10-03T16:56:39Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Roehre1.jpg 6 20 29 2007-10-03T16:56:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Roehre2.jpg 6 21 30 2007-10-03T16:57:12Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Strom.jpg 6 22 31 2007-10-03T16:57:32Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Takt-brd.gif 6 23 32 2007-10-03T16:57:51Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Takt-sch.gif 6 24 33 2007-10-03T16:58:08Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Tasten-auf.jpg 6 25 34 2007-10-03T16:58:46Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Tasten-sch.gif 6 26 35 2007-10-03T16:59:30Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Treiber-auf-hint.jpg 6 27 36 2007-10-03T16:59:45Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Treiber-auf-unten.jpg 6 28 37 2007-10-03T17:00:09Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Treiber-auf-unten-draht.jpg 6 29 38 2007-10-03T17:00:22Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Treiber-auf-vorne.jpg 6 30 39 2007-10-03T17:00:51Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Treiber-brd.gif 6 31 40 2007-10-03T17:01:09Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Treiber-sch.gif 6 32 41 2007-10-03T17:01:31Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nixie-Uhr.zip 6 33 42 2007-10-03T17:05:40Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Nixie-Uhr 0 34 43 2007-10-03T21:10:16Z Chris 2 ...to be continued... wikitext text/x-wiki Vor ein paar Wochen fand ich eine schon etwas betagte Platine mit ein paar Nixie-Röhren. Also schnell fragen, ob die Platine noch gebraucht wird und freuen, dass es nicht der Fall ist! == Aber halt, stopp, Moment! Was sind überhaupt Nixies? == Nixies sind mit Neon gefüllte Röhren, in denen sich dünne, aus Blech ausgestanzte Ziffern befinden. Diese Ziffern sind mit feinen Drähtchen mit "der Außenwelt" verbunden. Um die feinen Plättchen befindet sich ein feines Gitter, die Anode. Nixies funktionieren nach dem gleichen Prinzip wie Glimmlämpchen, der Glimmentladung. Die Nixie-Röhren sind (fast) immer wie folgt aufgebaut: [[Bild:Nixie-Aufbau.gif]] Damit die Plättchen zum leuchten angeregt werden, müssen sie wie Glimmlämpchen mit Spannung versorgt werden - mit dem Unterschied, dass bei Nixies Gleichspannung verwendet wird, da sonst auch das Gitter leuchtet. Wichtig ist hier nur noch, dass die Spannung stimmt (meist um die 60-90V) und dass die Kathode an Masse liegt. Jetzt habe ich ungefähr erklärt wie Nixies aufgebaut sind und wie sie funktionieren - aber woher kommt der Name? Ende der 50er hat die Entwicklung der "numerischen Indikatoren" in der Firma Burroughs begonnen. Dort wurden sie unter dem Namen "<u>N</u>umeric <u>I</u>ndicator E<u>x</u>perimental No. <u>1</u>" als Patent angemeldet, In der Firma war der Kurzname der Anzeigen "NIX 1". Da es sich auch als Nixi liest, bürgerte sich der Name "Nixie" relativ schnell ein (nachzulesen unter [http://www.vcalc.net/display2.htm http://www.vcalc.net/display2.htm]). Jetzt wäre schon einmal geklärt, was Nixies sind. Aber was soll ich mit ihnen machen? Inspiriert durch Internetseiten wie [http://www.crappythumb.de.vu/ CrappyThumb] ist es schnell klar: Es wird eine Uhr gebaut! Als erstes werden die Röhren genauer unter die Lupe genommen - ich will ja wissen, ob alle noch funktionieren. [[Bild:Nixie-Roehre1.jpg|thumb|NEC 236 LD8007]] So sehen sie aus: NEC 236 LD8007 mit schon fast niedlicher Zeichenhöhe von 10mm. Sie können Zahlen von 0-9 sowie einen Punkt darstellen. Der große Vorteil an den Röh(ch)ren: Die Beine sind mit der Halterung 2,54mm auseinander. Die Beine sind genauso wie bei einem IC im DIP 14 Gehäuse angeordnet. [[Bild:Nixie-Roehre2.jpg|thumb|Test einer Röhre]] Um zu testen, ob die Nixies noch leuchten, oder schon so viel Luft gesaugt haben, dass das Neon schon zu wenig ist, dass sie leuchten, habe ich die einzelnen Röhren kurz an meine Plasmakugel gehalten. Wie du auf dem Foto siehst, leuchtet außer der 4 auch das Neon am Glaskolben. Dies kommt allerdings daher, dass das Neon durch die hohe Spannung am Glaskörper angeregt wird. Im späteren Betrieb sieht man das Leuchten selbstverständlich nicht mehr. Rechts in der Nixie ist ein blauer Streifen zu sehen - das ist der Sauerstoff, das die Röhre mit der Zeit gesaugt hat. Alle Nixies sind soweit ok, bis auf dass sie eine schon sehr hohe Zündspannung von 90V haben. Da kommt auch schon die nächste Frage: Wie mit einer Logik-Schaltung, die mit 5V arbeitet, 90V schalten? Treiber-ICs, die 100V und mehr schalten können kosten einiges und bei BC548 o. ä. ist bei 30V Schluss. Relais? Nein. Erstens sind die zu laut und zweitens zu teuer. Die Lösung kommt von [http://www.fairchildsemi.com/ Fairchild]! Der gefundene Transistor nennt sich [http://www.fairchildsemi.com/ds/MP/MPSA42.pdf MSPA42] und reicht dicke für die Anwendung. VCES=300V und IC=500mA. ...und Wunder, oh Wunder: Reichelt bietet die Transistoren für 9ct das Stück an. Meine Uhr hat 6 Stellen, 10 Zahlen: 60 Transistoren. Aber Stopp: Normalerweise geht doch eine Uhr nur bis 23:59:59. Sprich: wir brauchen nicht 60 MPSA42, sondern nur noch 45. Somit erspart man etwas Geld und Lötarbeit. Aber was, wenn ein Transistor stirbt und einen Kurzschluss zwischen Basis und Kollektor verursacht? Einen absoluten Schutz möchte ich nicht einbauen, aber ein bisschen sollte schon drin sein: Ein 47k-Widerstand an der Basis begrenzt den, im Schadensfall fließenden Strom, auf etwa 5mA. Die Logik sollte das ganze zumindest für kurze Zeit aushalten können. Also: EAGLE anwerfen - jetzt wird gezeichnet! <gallery> Bild:Nixie-Treiber-sch.gif|Stromlaufplan der Treiberplatine Bild:Nixie-Treiber-brd.gif|Die ungerouteten Signale werden mit 0,2mm dünnem Lackdraht verbunden. Bild:Nixie-Treiber-auf-hint.jpg|...und aufgebaut Bild:Nixie-Treiber-auf-unten.jpg|Nach einigen Stunden Fädeln war das gröbste geschafft Bild:Nixie-Treiber-auf-unten-draht.jpg|Einen Tag später sah die Platine dann so aus. </gallery> Die länglichen "Dinger" oben sind die Röhren (der Streifen darin ist die Anode [Gitter], die Punkte die jeweiligen Ziffern), die Kreise dazwischen kleine Glimmlämpchen. Die Widerstände haben alle den Wert 47k 1/4W und die Transistoren sind MPSA42. Die Wirepads habe ich zur Übersichtlichkeit hinzugefügt, später werden die Flachbandkabel direkt an den Widerständen angelötet. Die Anoden der einzelnen Nixies könnte zusammengefasst werden. Ich habe sie getrennt gelassen, da man somit die Helligkeit der einzelnen Röhren besser einstellen kann. [[Bild:Nixie-Dimm-alt.jpg|thumb|none]] Damit die Helligkeit der einzelnen Röhren verändert werden kann, verwende ich Potis, die zusätzlich 100k-Widerstände zur Strombegrenzung besitzen. Der Widerstand lässt sich somit zwischen 100 und 200kΩ regeln. Jetzt geht es zum ersten Testlauf - aber Moment: Woher die Spannung für die Nixies nehmen? Netzspannung wäre möglich, den Knall, der bei einer Fehlfunktion auftreten werden würde, möchte ich nicht miterleben. Strombegrenzung durch Lastwiderstand? Nein, eine Heizung will ich nicht unbedingt bauen... Ein kleiner Trenntrafo wäre es, liegt momentan aber nicht herum. Dafür aber zwei 9V-Transformatoren! Beide haben einen nicht gleichgerichteten Ausgang, also ideal für meine Anwendung: Der erste Transformator wandelt die Netzspannung in 9V um, der zweite wieder zurück nach ungefähr 200V. Der erste Transformator liefert gleichzeitig die Spannung für die Logik-Schaltung. Das schöne an der ganzen Sache: Der Strom vom zweiten Trafo ist begrenzt und der Trafo ist galvanisch getrennt, was bedeutet, dass man Kontakt zu beiden Ausgängen am Trafo (bzw. dahinter) haben muss, um einen Stromschlag zu bekommen. Wenn man es genau nimmt ist aber auch diese Lösung nicht unbedingt optimal, da zweimal einiges an Energie als Wärme an den Transformatoren "verloren" gehen. Eine bessere Lösung hierfür wäre ein Schaltregler. Mehr dazu später. Die Nixies leuchten prima, als ich eine der Glimmlampen anschließe gibt es allerdings einen blauen Funken und einen lauten Knall. Sch... Vorwiderstand vergessen! Also schnell noch einen Vorwiderstand einbauen und an den Trafo anschließen (mit an die Stromversorgung der Nixies - Gleichstrom. Deshalb leuchtet auch nur eine Elektrode) [[Bild:Nixie-Glimmdef.jpg|thumb|Eine Glimmlampe, nachdem sie ohne Vorwiderstand an 120V betrieben wurde]] Rechts sieht man, wie es aussieht, wenn man eine Glimmlampe erst ohne Vorwiderstand und danach mit richtigem Vorwiderstand an Gleichstrom betreibt. Unten in der Lampe sprang ein Funke über und machte die Elektrode an der Stelle dicht. Mit Wechselstrom und ein bisschen Geduld (um die halbe Stunde) erholte sich die gute wieder und leuchtet nun (fast) wie vorher. :) Damit ich die Schaltung testen kann, muss noch das Netzteil gebaut werden. Die ungefähr 200VAC vom zweiten Transformator müssen gleichgerichtet und ein bisschen geglättet werden, damit sie nicht flackern. Die Glättungselkos sollten aber nicht allzu groß ausfallen, da es bei einem Kurzschluss sonst mächtig knallen kann. Ich habe 2 22µF/160V in Reihe geschaltet. sie halten somit 320V aus und die Kapazität halbiert sich auf 11µF. Damit sich die Elkos nach dem Abschalten möglichst schnell entladen (da die Röhren nur ab 90V merklich Stromaufnahme haben). Dazu habe ich 3 3MΩ 1/4W-Widerstände parallel geschaltet. Der Widerstandswert drittelt sich, die Leistungen addieren sich. Die Widerstände verbraten bei 200V zwar "nur" 0,04W (sie würden knapp das 18-fache aushalten) aber "sischär is sischär" ;) Die 5V für die Steuerung kommt von einem 78(L)05, der in Standard-Beschaltung betrieben wird (Gleichrichten, Glätten, 7805, 100nF Kerko, 100µF Elko). [[Bild:Nixie-Strom.jpg|thumb|none|Das: links unten die Anschlüsse für die Nixies, rechts für die Logik. Bei den Elkos links sollte man vermeiden, beide Gehäuse gleichzeitig zu berühren, da dort doch einiges an Spannung anliegt.]] == Steuerung == Hier muss man überlegen, was die Uhr überhaupt machen muss. Die wohl wichtigere Frage dürfte aber vorerst sein "womit?". Zähler gibt es ja sehr viele. Binäre oder dezimale Zähler mit xyz Ausgängen. Was wir hier brauchen wäre ein 10-Stufiger Zähler mit dezimalem Ausgang. Der [http://www.national.com/ds/CD/CD4017BC.pdf CD4017] kann das und ist bei Reichelt recht günstig zu bekommen. Jede Stelle der Uhr bekommt einen CD4017. Das Carry-Out der Einer der Sekunden, Minuten und Stunden wird mit dem Takteingang der Zehner verbunden. So kann die Uhr schon einmal die Sekunden, Minuten und Stunden zweistellig nach oben Zählen. Wen das Wort "Carry-Out" irritiert: Es ist ein Übertrag, der gerade für einen solchen Verwendungszweck eingebaut wurde. Man könnte statt dem Carry-Out-Signal auch den Ausgang für die 0 verwenden, aber wenn es schon einen Übertrag gibt, muss man keinen Umweg gehen. So weit, so gut - aber wie bringt man die Uhr dazu, nach 59 Sekunden dazu, den Sekundenzähler wieder auf 0 zu setzen und die Minuten eines weiter zu zählen (Selbes natürlich bei den Minuten)? Na klar: 60 Sekunden dürfen nicht erreicht werden, deshalb kommt an den Ausgang 6 der Sekunden-Zehner eine Verbindung zum Reset des ICs und gleichzeitig eine Verbindung zum Takteingang der Minuten-Einer. Ja wunderbar, das sollte so klappen. Aber ein Tag hat eine "krumme" Anzahl von Stunden. Bei 20 oder 30 Uhr auf 0 umschalten ist nicht drin. Die Uhr soll bei 24:00:00 auf 00:00:00 umspringen. Sprich: Der Stunden-Zehner muss den Wert 2 haben und gleichzeitig der Stunden-Einer den Wert 4. Ein UND-Gatter ([http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT32_4.pdf 74HCT32]) muss her! That's it - die Uhr würde jetzt schon funktionieren. Wobei... die Uhr würde mit einem geeigneten Taktgeber richtig funktionieren. Aber wer schaltet die Uhr jedes mal um Mitternacht ein, wenn er sie stellen will? Einfach kurz 5V an die Takteingänge anschließen geht nicht, da die ganzen ICs bei Low auf Masse ziehen. Dioden würden funktionieren, wenn aber Low (also GND) an den Dioden anliegt, kommt hinten nicht GND heraus, sondern ein unbestimmtes Signal zwischen GND und 5V. Genau das sollte man vermeiden, da sonst irgendwann die Uhr verstellt wird. ODER-Gatter sind hierfür eine bessere Lösung. Die Ausgänge der ODER-Verknüpfungen werden an die Takteingänge der jeweiligen Zähler angeschlossen (nur die Einer), ein Eingang der einzelen ODER wird an den Übertrag vom letzten Zähler angeschlossen, der zweite Eingang kommt an eine Buchsenleiste. Damit man die Uhr bequemer stellen kann und nicht immer der blöde Taktgeber stört, muss der Taktgeber abschaltbar sein. Mit einer UND-Verknüpfung lässt sich das ganze einfach lösen. Damit der Takt des Taktgebers bei Low von dem Eingang Clockset durchschaltet, wird Clockset über einen BC548 und 1k-Widerstand invertiert. Von den restlichen UND- und ODER-Verknüpfungen werden die Eingänge auf Masse gelegt. Somit wird vermieden, dass sie zum schwingen anfangen und evtl. den Betrieb stören. <gallery> Bild:Nixie-Logik-sch.gif|Das "Gehirn" der Uhr. Die Teile sind jeweils für Stunden, Minuten und Sekunden zuständig Bild:Nixie-Logik-brd.gif|Was als Stromlaufplan harmlos aussieht, ist auf dem Board ziemlich heftig. Warum hat der CD4017 eigentlich keine geordneten Ausgänge? Bild:Nixie-Logik-auf-oben.jpg|Die unbestückte, ungelötete Platine von oben... Bild:Nixie-Logik-auf-unten.jpg|Wenn man hier einen Fehler hat: Viel Spaß beim Suchen. </gallery> Mit dem Multimeter als Taktgenerator konnte die Uhr jetzt an den Start gehen. Damit ich nicht einen ganzen Tag warten muss um zu sehen, ob die Uhr nun funktioniert oder nicht, habe ich eine relativ hohe Frequenz im S/O gewählt. Mit 4kHz schafft man einen Tag in knapp 22 Sekunden. Bei 10kHz sind es nur noch ~9s ;) Um die Zeit zu stellen, habe ich eine kleine Tastatur-Platine gebaut. Wichtig ist bei den Tastern nur, dass sie nicht prellen. Aber welcher Taster ist prellfrei? Deshalb kommt eine kleine aber durchaus effektive Schaltung zum Einsatz, die die Taster entprellen soll: <gallery> Bild:Nixie-Tasten-sch.gif|Die Kondensatoren sind 100nF-Kerkos, die Widerstände haben alle den Wert 10k. S4 muss nicht entprellt werden, da die Uhr nicht unbedingt exakt einmal auf Knopfdruck resettet werden muss. Bild:Nixie-Tasten-auf.jpg|Leider habe ich das Board nach dem erstellen nicht gespeichert. Ein Foto tut's IMO auch ;) </gallery> 47bfa2c86118a1150c2323cd094b9c91dfbe1143 44 43 2007-10-07T15:10:48Z Chris 2 komplett von der alten Homepage übernommen wikitext text/x-wiki Vor ein paar Wochen fand ich eine schon etwas betagte Platine mit ein paar Nixie-Röhren. Also schnell fragen, ob die Platine noch gebraucht wird und freuen, dass es nicht der Fall ist! == Aber halt, stopp, Moment! Was sind überhaupt Nixies? == Nixies sind mit Neon gefüllte Röhren, in denen sich dünne, aus Blech ausgestanzte Ziffern befinden. Diese Ziffern sind mit feinen Drähtchen mit "der Außenwelt" verbunden. Um die feinen Plättchen befindet sich ein feines Gitter, die Anode. Nixies funktionieren nach dem gleichen Prinzip wie Glimmlämpchen, der Glimmentladung. Die Nixie-Röhren sind (fast) immer wie folgt aufgebaut: [[Bild:Nixie-Aufbau.gif]] Damit die Plättchen zum leuchten angeregt werden, müssen sie wie Glimmlämpchen mit Spannung versorgt werden - mit dem Unterschied, dass bei Nixies Gleichspannung verwendet wird, da sonst auch das Gitter leuchtet. Wichtig ist hier nur noch, dass die Spannung stimmt (meist um die 60-90V) und dass die Kathode an Masse liegt. Jetzt habe ich ungefähr erklärt wie Nixies aufgebaut sind und wie sie funktionieren - aber woher kommt der Name? Ende der 50er hat die Entwicklung der "numerischen Indikatoren" in der Firma Burroughs begonnen. Dort wurden sie unter dem Namen "<u>N</u>umeric <u>I</u>ndicator E<u>x</u>perimental No. <u>1</u>" als Patent angemeldet, In der Firma war der Kurzname der Anzeigen "NIX 1". Da es sich auch als Nixi liest, bürgerte sich der Name "Nixie" relativ schnell ein (nachzulesen unter [http://www.vcalc.net/display2.htm http://www.vcalc.net/display2.htm]). Jetzt wäre schon einmal geklärt, was Nixies sind. Aber was soll ich mit ihnen machen? Inspiriert durch Internetseiten wie [http://www.crappythumb.de.vu/ CrappyThumb] ist es schnell klar: Es wird eine Uhr gebaut! Als erstes werden die Röhren genauer unter die Lupe genommen - ich will ja wissen, ob alle noch funktionieren. [[Bild:Nixie-Roehre1.jpg|thumb|NEC 236 LD8007]] So sehen sie aus: NEC 236 LD8007 mit schon fast niedlicher Zeichenhöhe von 10mm. Sie können Zahlen von 0-9 sowie einen Punkt darstellen. Der große Vorteil an den Röh(ch)ren: Die Beine sind mit der Halterung 2,54mm auseinander. Die Beine sind genauso wie bei einem IC im DIP 14 Gehäuse angeordnet. [[Bild:Nixie-Roehre2.jpg|thumb|Test einer Röhre]] Um zu testen, ob die Nixies noch leuchten, oder schon so viel Luft gesaugt haben, dass das Neon schon zu wenig ist, dass sie leuchten, habe ich die einzelnen Röhren kurz an meine Plasmakugel gehalten. Wie du auf dem Foto siehst, leuchtet außer der 4 auch das Neon am Glaskolben. Dies kommt allerdings daher, dass das Neon durch die hohe Spannung am Glaskörper angeregt wird. Im späteren Betrieb sieht man das Leuchten selbstverständlich nicht mehr. Rechts in der Nixie ist ein blauer Streifen zu sehen - das ist der Sauerstoff, das die Röhre mit der Zeit gesaugt hat. Alle Nixies sind soweit ok, bis auf dass sie eine schon sehr hohe Zündspannung von 90V haben. Da kommt auch schon die nächste Frage: Wie mit einer Logik-Schaltung, die mit 5V arbeitet, 90V schalten? Treiber-ICs, die 100V und mehr schalten können kosten einiges und bei BC548 o. ä. ist bei 30V Schluss. Relais? Nein. Erstens sind die zu laut und zweitens zu teuer. Die Lösung kommt von [http://www.fairchildsemi.com/ Fairchild]! Der gefundene Transistor nennt sich [http://www.fairchildsemi.com/ds/MP/MPSA42.pdf MSPA42] und reicht dicke für die Anwendung. VCES=300V und IC=500mA. ...und Wunder, oh Wunder: Reichelt bietet die Transistoren für 9ct das Stück an. Meine Uhr hat 6 Stellen, 10 Zahlen: 60 Transistoren. Aber Stopp: Normalerweise geht doch eine Uhr nur bis 23:59:59. Sprich: wir brauchen nicht 60 MPSA42, sondern nur noch 45. Somit erspart man etwas Geld und Lötarbeit. Aber was, wenn ein Transistor stirbt und einen Kurzschluss zwischen Basis und Kollektor verursacht? Einen absoluten Schutz möchte ich nicht einbauen, aber ein bisschen sollte schon drin sein: Ein 47k-Widerstand an der Basis begrenzt den, im Schadensfall fließenden Strom, auf etwa 5mA. Die Logik sollte das ganze zumindest für kurze Zeit aushalten können. Also: EAGLE anwerfen - jetzt wird gezeichnet! <gallery> Bild:Nixie-Treiber-sch.gif|Stromlaufplan der Treiberplatine Bild:Nixie-Treiber-brd.gif|Die ungerouteten Signale werden mit 0,2mm dünnem Lackdraht verbunden. Bild:Nixie-Treiber-auf-hint.jpg|...und aufgebaut Bild:Nixie-Treiber-auf-unten.jpg|Nach einigen Stunden Fädeln war das gröbste geschafft Bild:Nixie-Treiber-auf-unten-draht.jpg|Einen Tag später sah die Platine dann so aus. </gallery> Die länglichen "Dinger" oben sind die Röhren (der Streifen darin ist die Anode [Gitter], die Punkte die jeweiligen Ziffern), die Kreise dazwischen kleine Glimmlämpchen. Die Widerstände haben alle den Wert 47k 1/4W und die Transistoren sind MPSA42. Die Wirepads habe ich zur Übersichtlichkeit hinzugefügt, später werden die Flachbandkabel direkt an den Widerständen angelötet. Die Anoden der einzelnen Nixies könnte zusammengefasst werden. Ich habe sie getrennt gelassen, da man somit die Helligkeit der einzelnen Röhren besser einstellen kann. [[Bild:Nixie-Dimm-alt.jpg|thumb|none]] Damit die Helligkeit der einzelnen Röhren verändert werden kann, verwende ich Potis, die zusätzlich 100k-Widerstände zur Strombegrenzung besitzen. Der Widerstand lässt sich somit zwischen 100 und 200kΩ regeln. Jetzt geht es zum ersten Testlauf - aber Moment: Woher die Spannung für die Nixies nehmen? Netzspannung wäre möglich, den Knall, der bei einer Fehlfunktion auftreten werden würde, möchte ich nicht miterleben. Strombegrenzung durch Lastwiderstand? Nein, eine Heizung will ich nicht unbedingt bauen... Ein kleiner Trenntrafo wäre es, liegt momentan aber nicht herum. Dafür aber zwei 9V-Transformatoren! Beide haben einen nicht gleichgerichteten Ausgang, also ideal für meine Anwendung: Der erste Transformator wandelt die Netzspannung in 9V um, der zweite wieder zurück nach ungefähr 200V. Der erste Transformator liefert gleichzeitig die Spannung für die Logik-Schaltung. Das schöne an der ganzen Sache: Der Strom vom zweiten Trafo ist begrenzt und der Trafo ist galvanisch getrennt, was bedeutet, dass man Kontakt zu beiden Ausgängen am Trafo (bzw. dahinter) haben muss, um einen Stromschlag zu bekommen. Wenn man es genau nimmt ist aber auch diese Lösung nicht unbedingt optimal, da zweimal einiges an Energie als Wärme an den Transformatoren "verloren" gehen. Eine bessere Lösung hierfür wäre ein Schaltregler. Mehr dazu später. Die Nixies leuchten prima, als ich eine der Glimmlampen anschließe gibt es allerdings einen blauen Funken und einen lauten Knall. Sch... Vorwiderstand vergessen! Also schnell noch einen Vorwiderstand einbauen und an den Trafo anschließen (mit an die Stromversorgung der Nixies - Gleichstrom. Deshalb leuchtet auch nur eine Elektrode) [[Bild:Nixie-Glimmdef.jpg|thumb|Eine Glimmlampe, nachdem sie ohne Vorwiderstand an 120V betrieben wurde]] Rechts sieht man, wie es aussieht, wenn man eine Glimmlampe erst ohne Vorwiderstand und danach mit richtigem Vorwiderstand an Gleichstrom betreibt. Unten in der Lampe sprang ein Funke über und machte die Elektrode an der Stelle dicht. Mit Wechselstrom und ein bisschen Geduld (um die halbe Stunde) erholte sich die gute wieder und leuchtet nun (fast) wie vorher. :) Damit ich die Schaltung testen kann, muss noch das Netzteil gebaut werden. Die ungefähr 200VAC vom zweiten Transformator müssen gleichgerichtet und ein bisschen geglättet werden, damit sie nicht flackern. Die Glättungselkos sollten aber nicht allzu groß ausfallen, da es bei einem Kurzschluss sonst mächtig knallen kann. Ich habe 2 22µF/160V in Reihe geschaltet. sie halten somit 320V aus und die Kapazität halbiert sich auf 11µF. Damit sich die Elkos nach dem Abschalten möglichst schnell entladen (da die Röhren nur ab 90V merklich Stromaufnahme haben). Dazu habe ich 3 3MΩ 1/4W-Widerstände parallel geschaltet. Der Widerstandswert drittelt sich, die Leistungen addieren sich. Die Widerstände verbraten bei 200V zwar "nur" 0,04W (sie würden knapp das 18-fache aushalten) aber "sischär is sischär" ;) Die 5V für die Steuerung kommt von einem 78(L)05, der in Standard-Beschaltung betrieben wird (Gleichrichten, Glätten, 7805, 100nF Kerko, 100µF Elko). [[Bild:Nixie-Strom.jpg|thumb|none|Das: links unten die Anschlüsse für die Nixies, rechts für die Logik. Bei den Elkos links sollte man vermeiden, beide Gehäuse gleichzeitig zu berühren, da dort doch einiges an Spannung anliegt.]] == Steuerung == Hier muss man überlegen, was die Uhr überhaupt machen muss. Die wohl wichtigere Frage dürfte aber vorerst sein "womit?". Zähler gibt es ja sehr viele. Binäre oder dezimale Zähler mit xyz Ausgängen. Was wir hier brauchen wäre ein 10-Stufiger Zähler mit dezimalem Ausgang. Der [http://www.national.com/ds/CD/CD4017BC.pdf CD4017] kann das und ist bei Reichelt recht günstig zu bekommen. Jede Stelle der Uhr bekommt einen CD4017. Das Carry-Out der Einer der Sekunden, Minuten und Stunden wird mit dem Takteingang der Zehner verbunden. So kann die Uhr schon einmal die Sekunden, Minuten und Stunden zweistellig nach oben Zählen. Wen das Wort "Carry-Out" irritiert: Es ist ein Übertrag, der gerade für einen solchen Verwendungszweck eingebaut wurde. Man könnte statt dem Carry-Out-Signal auch den Ausgang für die 0 verwenden, aber wenn es schon einen Übertrag gibt, muss man keinen Umweg gehen. So weit, so gut - aber wie bringt man die Uhr dazu, nach 59 Sekunden dazu, den Sekundenzähler wieder auf 0 zu setzen und die Minuten eines weiter zu zählen (Selbes natürlich bei den Minuten)? Na klar: 60 Sekunden dürfen nicht erreicht werden, deshalb kommt an den Ausgang 6 der Sekunden-Zehner eine Verbindung zum Reset des ICs und gleichzeitig eine Verbindung zum Takteingang der Minuten-Einer. Ja wunderbar, das sollte so klappen. Aber ein Tag hat eine "krumme" Anzahl von Stunden. Bei 20 oder 30 Uhr auf 0 umschalten ist nicht drin. Die Uhr soll bei 24:00:00 auf 00:00:00 umspringen. Sprich: Der Stunden-Zehner muss den Wert 2 haben und gleichzeitig der Stunden-Einer den Wert 4. Ein UND-Gatter ([http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT32_4.pdf 74HCT32]) muss her! That's it - die Uhr würde jetzt schon funktionieren. Wobei... die Uhr würde mit einem geeigneten Taktgeber richtig funktionieren. Aber wer schaltet die Uhr jedes mal um Mitternacht ein, wenn er sie stellen will? Einfach kurz 5V an die Takteingänge anschließen geht nicht, da die ganzen ICs bei Low auf Masse ziehen. Dioden würden funktionieren, wenn aber Low (also GND) an den Dioden anliegt, kommt hinten nicht GND heraus, sondern ein unbestimmtes Signal zwischen GND und 5V. Genau das sollte man vermeiden, da sonst irgendwann die Uhr verstellt wird. ODER-Gatter sind hierfür eine bessere Lösung. Die Ausgänge der ODER-Verknüpfungen werden an die Takteingänge der jeweiligen Zähler angeschlossen (nur die Einer), ein Eingang der einzelen ODER wird an den Übertrag vom letzten Zähler angeschlossen, der zweite Eingang kommt an eine Buchsenleiste. Damit man die Uhr bequemer stellen kann und nicht immer der blöde Taktgeber stört, muss der Taktgeber abschaltbar sein. Mit einer UND-Verknüpfung lässt sich das ganze einfach lösen. Damit der Takt des Taktgebers bei Low von dem Eingang Clockset durchschaltet, wird Clockset über einen BC548 und 1k-Widerstand invertiert. Von den restlichen UND- und ODER-Verknüpfungen werden die Eingänge auf Masse gelegt. Somit wird vermieden, dass sie zum schwingen anfangen und evtl. den Betrieb stören. <gallery> Bild:Nixie-Logik-sch.gif|Das "Gehirn" der Uhr. Die Teile sind jeweils für Stunden, Minuten und Sekunden zuständig Bild:Nixie-Logik-brd.gif|Was als Stromlaufplan harmlos aussieht, ist auf dem Board ziemlich heftig. Warum hat der CD4017 eigentlich keine geordneten Ausgänge? Bild:Nixie-Logik-auf-oben.jpg|Die unbestückte, ungelötete Platine von oben... Bild:Nixie-Logik-auf-unten.jpg|Wenn man hier einen Fehler hat: Viel Spaß beim Suchen. </gallery> Mit dem Multimeter als Taktgenerator konnte die Uhr jetzt an den Start gehen. Damit ich nicht einen ganzen Tag warten muss um zu sehen, ob die Uhr nun funktioniert oder nicht, habe ich eine relativ hohe Frequenz im S/O gewählt. Mit 4kHz schafft man einen Tag in knapp 22 Sekunden. Bei 10kHz sind es nur noch ~9s ;) Um die Zeit zu stellen, habe ich eine kleine Tastatur-Platine gebaut. Wichtig ist bei den Tastern nur, dass sie nicht prellen. Aber welcher Taster ist prellfrei? Deshalb kommt eine kleine aber durchaus effektive Schaltung zum Einsatz, die die Taster entprellen soll: <gallery> Bild:Nixie-Tasten-sch.gif|Stromlaufplan für die Tastatur Bild:Nixie-Tasten-auf.jpg|Leider habe ich das Board nach dem erstellen nicht gespeichert. Ein Foto tut's IMO auch ;) </gallery> Jetzt aber zum heikelsten Thema: der Taktgeber. Zum Testen der Uhr nahm ich mein DMM, das einen Taktausgang hat - aber auf Dauer ist ein klobiges, stromfressendes Multimeter keine Lösung für eine Uhr. Die erste Idee: ein Quarz-Oszillator. Ich hab doch mal was mit einem [http://www.national.com/ds/CD/CD4060BC.pdf CD4060] und einem 32,nochwas kHz-Quarz gelesen. Schnell das Datenblatt vom CD4060 überflogen... Das Teil sieht auf den ersten Blick recht gut aus, auf dem zweiten Blick sieht man, dass der höchste Teiler 214 ist. Bei dem 32,768kHz würde über den Teiler 2Hz herauskommen. Irgendwie muss man doch auf 1Hz kommen. Es liegen doch sicher noch ein paar CD4017 herum - die können doch zählen! Wenn man an einem CD4017 Q2 mit Reset verbindet, wird nach jeden zweiten Impuls an Q1 ein Takt ausgegeben. Das sollte funktionieren. Ein paar CD4060 und ein 32,768kHz-Quarz liegen gaaanz zufällig von der letzten Reichelt-Bestellung herum. Also schnell zum Testen mit 33pF-Kerkos einen Oszillator aufbauen... ..und: nix ist! Nur wenn ich mit dem DMM an Masse und Pin 9 messe, kommt hinten was halbwegs vernünftiges raus. Warum? Na, der Fehler sitzt natürlich davor! Ich habe natürlich das Datenblatt des CD4060 nur halb gelesen und Seite 4 übersehen, wo sich eine Schaltung für genau so eine Anwendung befindet. Laut Zeichnung sollte man einen 10pF und einen variablen Kondensator nehmen. Beides liegt nicht herum und ich war einen Tag vorher schon in meiner Elektro-"Apotheke". Ähnliche Werte sind da - also ein bisschen experimentieren. Irgendwann läuft der Quarz-Oszillator auch - aber naja, ein bisschen ungenau. Die Abweichung beträgt im Vergleich zur Funkuhr etwa 5s pro Minute. Okay, mich wundert's nicht, da ich ja alles andere als richtige Werte habe. Als ich die Leuchtstofflampe an meinem Werktisch abschalte bleibt plötzlich die Uhr stehen. Nichts geht mehr - $#!†. Also mal gucken, was die "Kollegen" so machen. CrappyThumb hat einen [http://pdfserv.maxim-ic.com/en/ds/DS1603.pdf DS1603], der eigentlich eine RTC ist, missbraucht und nutzt den Taktausgang für seine Uhr. Nachteil an dem IC: groß, teuer und schwer zu beschaffen. Rein "zufällig" habe ich zwei dieser ICs ergattern können. Pin 2-5 und 7 sind Masse, Pin 1 ist VDD und Pin 6 ist der Taktausgang. Wenn man den IC nun "normal" anschließt, gibt er noch keinen Takt aus. Um ihm nun einen Takt zu entlocken, muss er kurz (!!) verpolt angeschlossen werden (Strombegrenzung auf ein paar mA wäre hierbei angebracht). Der Timer hat eine Abweichung von ±2 Minuten pro Monat und ist somit schon recht genau. Wer auf extrem hohe Genauigkeit steht, kann nach einem DS32kHz Ausschau halten. Dies ist ein TCXO (=Temperaturkompensierter Quarzoszillator) und hat im Temperaturbereich zwischen 0 und +40°C eine Abweichung um ±1 Minute ''pro Jahr''! Bei konstanter Raumtemperatur dürfte die Genauigkeit noch deutlich höher sein. Wie schon der Name des ICs, gibt er einen Takt von 32kHz aus. Genauer: 32,768kHz - er kann somit direkt als Quarz-Ersatz an meine Schaltung angeschlossen werden: <gallery> Bild:Nixie-Takt-sch.gif Bild:Nixie-Takt-brd.gif </gallery> Durch kleine Veränderungen kann auch ein "normaler" Quarz angeschlossen werden. Eine weitere Methode um an einen 1Hz-Takt zu gelangen ist die Netzfrequenz. Auf lange Dauer macht das Sinn, für Sekundengenaue Anzeige ist allerdings nichts, da sie ständig etwas schwankt. <gallery> Bild:Nixie-Treiber-auf-vorne.jpg|Die Uhr in Urform von vorne Bild:Nixie-beta.jpg|Überblick über die ganze Uhr </gallery> [[Bild:Nixie-fertig.jpg|thumb|Die (äußerlich) fertige Nixie-Uhr]] Da die Uhr noch ein bisschen nackt ist, bekommt sie ein Holzgehäuse. Mit 110x110x110mm ist es recht knapp bemessen - die Elektronik passte gerade noch hinein. Die viel zu langen Flachbandkabel habe ich um die Uhrensteuerung gewickelt, damit es den Deckel nicht andauernd anhebt ;) Der Transformator für die 200V der Nixies kam gemeinsam mit der Spannungsstabilisierung unter eine Abdeckung (bestehend aus zerschnittenen CD-Hüllen). So ist die restliche Elektronik ein wenig vor der höheren Spannung geschützt. Eines stört mich aber noch an der Uhr. Am Tag kann man sie wegen der hellen Zahlen super ablesen, wenn man aber schlafen möchte, kann man nicht (zumindest ich), da das Teil das halbe Zimmer erhellt. Zeit ablesen ist auch nicht drin, da sich die Zahlen nicht deutlich genug abheben. Die Potis für die einzelnen Ziffern kann ich zwar herunterdrehen, dann sind die Ziffern jedoch gar nicht mehr zu sehen, da sie nur noch teilweise glimmen. Fahrtregler und ähnliche Motor-"dimmer" haben doch Pulsweitenmodulatoren eingebaut, das müsste man doch übertragen können!? Das menschliche Auge ist sowieso sehr träge und würde es nicht merken, wenn die Röhren vor sich hin "flackern". Also einen PWM mit dem NE555 aufbauen und schauen, wie es aussieht. Aber halt! Wie soll ich die Nixies schalten? Wenn ich die Anoden der Röhren mit einem MPSA42 schalte, habe ich knapp 200V auf der Logik, die sich dann mit einer Rauchwolke verabschieden würde... Also müssen die Kathoden der Röhren geschalten werden. Im Prinzip gibt es das gleiche Problem, da so wieder 200V auf meine 5V gelangen können. Naja, egal - zum Testen muss das Labor-Netzteil herhalten. Der PWM dimmt die Nixies zwar, das Ergebnis sieht aber ähnlich wie mit normalen Potentiometern aus. Irgendwie wundert es mich im Nachhinein auch nicht - die Schaltfrequenz war mit 10kHz viel zu hoch. Also auf etwa 1kHz heruntertrimmen und noch mal versuchen: Das Ergebnis sieht gut bis super aus. Auch bei sehr geringer Helligkeit werden die Zahlen wesentlich besser als mit den Potis angezeigt. Sogar der obere Teil der 5 glimmt perfekt. Vorher konnte ich dies nur mit sehr hohem Strom erreichen (was die Nixies nicht besonders lange mitmachen). Der PWM hat noch einen zweiten schönen Nebeneffekt: Die glimmenden Bereiche werden schärfer abgegrenzt und die Umgebung um die Filamente leuchten nicht mehr leicht bläulich :). Der Bau des Pulsweitenmodulators war somit in jeder Hinsicht lohnenswert. Der Haken an der Sache ist aber noch immer: Das Teil braucht eine galvanisch getrennte Stromversorgung. Ich hatte Glück und fand in meinem Pollin-Schrottsorti einen 5V DC-DC-Wandler - was aber für den Nachbau? Extra für den popeligen PWM einen stinkteueren DC-DC-Wandler oder einen Schaltregler verbauen? Das kann's doch nicht sein. Irgendwann in der Nacht fiel mir dann ein, dass nicht unbedingt die Stromversorgung getrennt sein muss, es kann doch auch der Signalausgang sein und dafür gibt es Optokoppler. Falls der Ausgang dann auch noch die Glimmspannung und den erforderlichen Strom aushalten, kann die Transistorstufe danach weggelassen werden. Die Schaltung sieht dann folgendermaßen aus: <gallery> Bild:Nixie-Dimm-sch.gif|Auf den Optionalen Teil kann verzichtet werden, wenn der Optokoppler den Nennstrom der Röhren abkann Nixie-Dimm-brd.gif|Die Platine wäre geätzt etwa 40x16mm groß. </gallery> Als ich den PWM samt DC-DC-Wandler anschloss und in die Uhr einbaute, zeigte sich ein "kleiner" Nachteil des Dimmers: Die Uhr zählt jetzt wieder wie bescheuert. Wenn ich auf den Sekunden-Taster drücke, bleibt sie allerdings ruhig. Irgendetwas muss also vor dem ODER (IC9B) nicht ganz stimmen. 100nF an Pin 5 gegen Masse und Ruhe war. Irgendwie scheint aber noch etwas an der Logik madig zu sein - Über Nacht fehlen oft einige Sekunden. Überprüfen, wo genau der Fehler nun steckt bzw. schauen, wo genau ein Signal unsauer ist, kann ich wegen fehlendem Oszi nicht. Vielleicht kann ich das mal bei meinem Bekannten oder in der Schule ausmessen (zum "fröhlichen Messen" hab ich leider nicht genug Hohlstunden). Zum Überprüfen der "verbuggten" Stellen war kein Oszi nötig. Ein wenig Intuition und ein paar mehr 1k-Widerstände halfen schon: - Pulldown an IC8 Pin 5 - Pulldown an SV9 Pin 1 Wenn die Uhr störungsfrei ohne Tastatur betrieben werden soll, Pulldowns an SV9 Pin 2-5 löten. Die EAGLE-Dateien gibt es selbstverständlich auch [[Bild:Nixie-Uhr.zip|zum herunterladen]]. == Nachtrag (09/2007) == Mittlerweile ist die Uhr leider kein zuverlässes Zeitanzeige-Werkzeug mehr. Irgendwo habe ich mich verlötet - das Ding weicht nach kurzer Zeit ziemlich vom Soll ab und die Überlegung steht nahe, ob ich die Uhr nicht einfach mit einem AVR und DCF-77-Empfänger aufwerte. Das Dimmen per PWM ist übrigens spitze, auch wenn mir damals in d.s.e. davon dringend abgeraten wurde (Lebensdauer der Röhren). Allerdings erfreuen sich die Nixies immernoch allerbester Leuchtkraft und werden es hoffentlich auch noch lange tun. 5bfac108d556dc1c5986c4bd839f04904d352676 45 44 2007-10-07T15:21:20Z Chris 2 wikitext text/x-wiki Vor ein paar Wochen fand ich eine schon etwas betagte Platine mit ein paar Nixie-Röhren. Also schnell fragen, ob die Platine noch gebraucht wird und freuen, dass es nicht der Fall ist! == Aber halt, stopp, Moment! Was sind überhaupt Nixies? == Nixies sind mit Neon gefüllte Röhren, in denen sich dünne, aus Blech ausgestanzte Ziffern befinden. Diese Ziffern sind mit feinen Drähtchen mit "der Außenwelt" verbunden. Um die feinen Plättchen befindet sich ein feines Gitter, die Anode. Nixies funktionieren nach dem gleichen Prinzip wie Glimmlämpchen, der Glimmentladung. Die Nixie-Röhren sind (fast) immer wie folgt aufgebaut: [[Bild:Nixie-Aufbau.gif]] Damit die Plättchen zum leuchten angeregt werden, müssen sie wie Glimmlämpchen mit Spannung versorgt werden - mit dem Unterschied, dass bei Nixies Gleichspannung verwendet wird, da sonst auch das Gitter leuchtet. Wichtig ist hier nur noch, dass die Spannung stimmt (meist um die 60-90V) und dass die Kathode an Masse liegt. Jetzt habe ich ungefähr erklärt wie Nixies aufgebaut sind und wie sie funktionieren - aber woher kommt der Name? Ende der 50er hat die Entwicklung der "numerischen Indikatoren" in der Firma Burroughs begonnen. Dort wurden sie unter dem Namen "<u>N</u>umeric <u>I</u>ndicator E<u>x</u>perimental No. <u>1</u>" als Patent angemeldet, In der Firma war der Kurzname der Anzeigen "NIX 1". Da es sich auch als Nixi liest, bürgerte sich der Name "Nixie" relativ schnell ein (nachzulesen unter [http://www.vcalc.net/display2.htm http://www.vcalc.net/display2.htm]). Jetzt wäre schon einmal geklärt, was Nixies sind. Aber was soll ich mit ihnen machen? Inspiriert durch Internetseiten wie [http://www.crappythumb.de.vu/ CrappyThumb] ist es schnell klar: Es wird eine Uhr gebaut! Als erstes werden die Röhren genauer unter die Lupe genommen - ich will ja wissen, ob alle noch funktionieren. [[Bild:Nixie-Roehre1.jpg|thumb|NEC 236 LD8007]] So sehen sie aus: NEC 236 LD8007 mit schon fast niedlicher Zeichenhöhe von 10mm. Sie können Zahlen von 0-9 sowie einen Punkt darstellen. Der große Vorteil an den Röh(ch)ren: Die Beine sind mit der Halterung 2,54mm auseinander. Die Beine sind genauso wie bei einem IC im DIP 14 Gehäuse angeordnet. [[Bild:Nixie-Roehre2.jpg|thumb|Test einer Röhre]] Um zu testen, ob die Nixies noch leuchten, oder schon so viel Luft gesaugt haben, dass das Neon schon zu wenig ist, dass sie leuchten, habe ich die einzelnen Röhren kurz an meine Plasmakugel gehalten. Wie du auf dem Foto siehst, leuchtet außer der 4 auch das Neon am Glaskolben. Dies kommt allerdings daher, dass das Neon durch die hohe Spannung am Glaskörper angeregt wird. Im späteren Betrieb sieht man das Leuchten selbstverständlich nicht mehr. Rechts in der Nixie ist ein blauer Streifen zu sehen - das ist der Sauerstoff, das die Röhre mit der Zeit gesaugt hat. Alle Nixies sind soweit ok, bis auf dass sie eine schon sehr hohe Zündspannung von 90V haben. Da kommt auch schon die nächste Frage: Wie mit einer Logik-Schaltung, die mit 5V arbeitet, 90V schalten? Treiber-ICs, die 100V und mehr schalten können kosten einiges und bei BC548 o. ä. ist bei 30V Schluss. Relais? Nein. Erstens sind die zu laut und zweitens zu teuer. Die Lösung kommt von [http://www.fairchildsemi.com/ Fairchild]! Der gefundene Transistor nennt sich [http://www.fairchildsemi.com/ds/MP/MPSA42.pdf MSPA42] und reicht dicke für die Anwendung. VCES=300V und IC=500mA. ...und Wunder, oh Wunder: Reichelt bietet die Transistoren für 9ct das Stück an. Meine Uhr hat 6 Stellen, 10 Zahlen: 60 Transistoren. Aber Stopp: Normalerweise geht doch eine Uhr nur bis 23:59:59. Sprich: wir brauchen nicht 60 MPSA42, sondern nur noch 45. Somit erspart man etwas Geld und Lötarbeit. Aber was, wenn ein Transistor stirbt und einen Kurzschluss zwischen Basis und Kollektor verursacht? Einen absoluten Schutz möchte ich nicht einbauen, aber ein bisschen sollte schon drin sein: Ein 47k-Widerstand an der Basis begrenzt den, im Schadensfall fließenden Strom, auf etwa 5mA. Die Logik sollte das ganze zumindest für kurze Zeit aushalten können. Also: EAGLE anwerfen - jetzt wird gezeichnet! <gallery> Bild:Nixie-Treiber-sch.gif|Stromlaufplan der Treiberplatine Bild:Nixie-Treiber-brd.gif|Die ungerouteten Signale werden mit 0,2mm dünnem Lackdraht verbunden. Bild:Nixie-Treiber-auf-hint.jpg|...und aufgebaut Bild:Nixie-Treiber-auf-unten.jpg|Nach einigen Stunden Fädeln war das gröbste geschafft Bild:Nixie-Treiber-auf-unten-draht.jpg|Einen Tag später sah die Platine dann so aus. </gallery> Die länglichen "Dinger" oben sind die Röhren (der Streifen darin ist die Anode [Gitter], die Punkte die jeweiligen Ziffern), die Kreise dazwischen kleine Glimmlämpchen. Die Widerstände haben alle den Wert 47k 1/4W und die Transistoren sind MPSA42. Die Wirepads habe ich zur Übersichtlichkeit hinzugefügt, später werden die Flachbandkabel direkt an den Widerständen angelötet. Die Anoden der einzelnen Nixies könnte zusammengefasst werden. Ich habe sie getrennt gelassen, da man somit die Helligkeit der einzelnen Röhren besser einstellen kann. [[Bild:Nixie-Dimm-alt.jpg|thumb|none]] Damit die Helligkeit der einzelnen Röhren verändert werden kann, verwende ich Potis, die zusätzlich 100k-Widerstände zur Strombegrenzung besitzen. Der Widerstand lässt sich somit zwischen 100 und 200kΩ regeln. Jetzt geht es zum ersten Testlauf - aber Moment: Woher die Spannung für die Nixies nehmen? Netzspannung wäre möglich, den Knall, der bei einer Fehlfunktion auftreten werden würde, möchte ich nicht miterleben. Strombegrenzung durch Lastwiderstand? Nein, eine Heizung will ich nicht unbedingt bauen... Ein kleiner Trenntrafo wäre es, liegt momentan aber nicht herum. Dafür aber zwei 9V-Transformatoren! Beide haben einen nicht gleichgerichteten Ausgang, also ideal für meine Anwendung: Der erste Transformator wandelt die Netzspannung in 9V um, der zweite wieder zurück nach ungefähr 200V. Der erste Transformator liefert gleichzeitig die Spannung für die Logik-Schaltung. Das schöne an der ganzen Sache: Der Strom vom zweiten Trafo ist begrenzt und der Trafo ist galvanisch getrennt, was bedeutet, dass man Kontakt zu beiden Ausgängen am Trafo (bzw. dahinter) haben muss, um einen Stromschlag zu bekommen. Wenn man es genau nimmt ist aber auch diese Lösung nicht unbedingt optimal, da zweimal einiges an Energie als Wärme an den Transformatoren "verloren" gehen. Eine bessere Lösung hierfür wäre ein Schaltregler. Mehr dazu später. Die Nixies leuchten prima, als ich eine der Glimmlampen anschließe gibt es allerdings einen blauen Funken und einen lauten Knall. Sch... Vorwiderstand vergessen! Also schnell noch einen Vorwiderstand einbauen und an den Trafo anschließen (mit an die Stromversorgung der Nixies - Gleichstrom. Deshalb leuchtet auch nur eine Elektrode) [[Bild:Nixie-Glimmdef.jpg|thumb|Eine Glimmlampe, nachdem sie ohne Vorwiderstand an 120V betrieben wurde]] Rechts sieht man, wie es aussieht, wenn man eine Glimmlampe erst ohne Vorwiderstand und danach mit richtigem Vorwiderstand an Gleichstrom betreibt. Unten in der Lampe sprang ein Funke über und machte die Elektrode an der Stelle dicht. Mit Wechselstrom und ein bisschen Geduld (um die halbe Stunde) erholte sich die gute wieder und leuchtet nun (fast) wie vorher. :) Damit ich die Schaltung testen kann, muss noch das Netzteil gebaut werden. Die ungefähr 200VAC vom zweiten Transformator müssen gleichgerichtet und ein bisschen geglättet werden, damit sie nicht flackern. Die Glättungselkos sollten aber nicht allzu groß ausfallen, da es bei einem Kurzschluss sonst mächtig knallen kann. Ich habe 2 22µF/160V in Reihe geschaltet. sie halten somit 320V aus und die Kapazität halbiert sich auf 11µF. Damit sich die Elkos nach dem Abschalten möglichst schnell entladen (da die Röhren nur ab 90V merklich Stromaufnahme haben). Dazu habe ich 3 3MΩ 1/4W-Widerstände parallel geschaltet. Der Widerstandswert drittelt sich, die Leistungen addieren sich. Die Widerstände verbraten bei 200V zwar "nur" 0,04W (sie würden knapp das 18-fache aushalten) aber "sischär is sischär" ;) Die 5V für die Steuerung kommt von einem 78(L)05, der in Standard-Beschaltung betrieben wird (Gleichrichten, Glätten, 7805, 100nF Kerko, 100µF Elko). [[Bild:Nixie-Strom.jpg|thumb|none|Das: links unten die Anschlüsse für die Nixies, rechts für die Logik. Bei den Elkos links sollte man vermeiden, beide Gehäuse gleichzeitig zu berühren, da dort doch einiges an Spannung anliegt.]] == Steuerung == Hier muss man überlegen, was die Uhr überhaupt machen muss. Die wohl wichtigere Frage dürfte aber vorerst sein "womit?". Zähler gibt es ja sehr viele. Binäre oder dezimale Zähler mit xyz Ausgängen. Was wir hier brauchen wäre ein 10-Stufiger Zähler mit dezimalem Ausgang. Der [http://www.national.com/ds/CD/CD4017BC.pdf CD4017] kann das und ist bei Reichelt recht günstig zu bekommen. Jede Stelle der Uhr bekommt einen CD4017. Das Carry-Out der Einer der Sekunden, Minuten und Stunden wird mit dem Takteingang der Zehner verbunden. So kann die Uhr schon einmal die Sekunden, Minuten und Stunden zweistellig nach oben Zählen. Wen das Wort "Carry-Out" irritiert: Es ist ein Übertrag, der gerade für einen solchen Verwendungszweck eingebaut wurde. Man könnte statt dem Carry-Out-Signal auch den Ausgang für die 0 verwenden, aber wenn es schon einen Übertrag gibt, muss man keinen Umweg gehen. So weit, so gut - aber wie bringt man die Uhr dazu, nach 59 Sekunden dazu, den Sekundenzähler wieder auf 0 zu setzen und die Minuten eines weiter zu zählen (Selbes natürlich bei den Minuten)? Na klar: 60 Sekunden dürfen nicht erreicht werden, deshalb kommt an den Ausgang 6 der Sekunden-Zehner eine Verbindung zum Reset des ICs und gleichzeitig eine Verbindung zum Takteingang der Minuten-Einer. Ja wunderbar, das sollte so klappen. Aber ein Tag hat eine "krumme" Anzahl von Stunden. Bei 20 oder 30 Uhr auf 0 umschalten ist nicht drin. Die Uhr soll bei 24:00:00 auf 00:00:00 umspringen. Sprich: Der Stunden-Zehner muss den Wert 2 haben und gleichzeitig der Stunden-Einer den Wert 4. Ein UND-Gatter ([http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT32_4.pdf 74HCT32]) muss her! That's it - die Uhr würde jetzt schon funktionieren. Wobei... die Uhr würde mit einem geeigneten Taktgeber richtig funktionieren. Aber wer schaltet die Uhr jedes mal um Mitternacht ein, wenn er sie stellen will? Einfach kurz 5V an die Takteingänge anschließen geht nicht, da die ganzen ICs bei Low auf Masse ziehen. Dioden würden funktionieren, wenn aber Low (also GND) an den Dioden anliegt, kommt hinten nicht GND heraus, sondern ein unbestimmtes Signal zwischen GND und 5V. Genau das sollte man vermeiden, da sonst irgendwann die Uhr verstellt wird. ODER-Gatter sind hierfür eine bessere Lösung. Die Ausgänge der ODER-Verknüpfungen werden an die Takteingänge der jeweiligen Zähler angeschlossen (nur die Einer), ein Eingang der einzelen ODER wird an den Übertrag vom letzten Zähler angeschlossen, der zweite Eingang kommt an eine Buchsenleiste. Damit man die Uhr bequemer stellen kann und nicht immer der blöde Taktgeber stört, muss der Taktgeber abschaltbar sein. Mit einer UND-Verknüpfung lässt sich das ganze einfach lösen. Damit der Takt des Taktgebers bei Low von dem Eingang Clockset durchschaltet, wird Clockset über einen BC548 und 1k-Widerstand invertiert. Von den restlichen UND- und ODER-Verknüpfungen werden die Eingänge auf Masse gelegt. Somit wird vermieden, dass sie zum schwingen anfangen und evtl. den Betrieb stören. <gallery> Bild:Nixie-Logik-sch.gif|Das "Gehirn" der Uhr. Die Teile sind jeweils für Stunden, Minuten und Sekunden zuständig Bild:Nixie-Logik-brd.gif|Was als Stromlaufplan harmlos aussieht, ist auf dem Board ziemlich heftig. Warum hat der CD4017 eigentlich keine geordneten Ausgänge? Bild:Nixie-Logik-auf-oben.jpg|Die unbestückte, ungelötete Platine von oben... Bild:Nixie-Logik-auf-unten.jpg|Wenn man hier einen Fehler hat: Viel Spaß beim Suchen. </gallery> Mit dem Multimeter als Taktgenerator konnte die Uhr jetzt an den Start gehen. Damit ich nicht einen ganzen Tag warten muss um zu sehen, ob die Uhr nun funktioniert oder nicht, habe ich eine relativ hohe Frequenz im S/O gewählt. Mit 4kHz schafft man einen Tag in knapp 22 Sekunden. Bei 10kHz sind es nur noch ~9s ;) Um die Zeit zu stellen, habe ich eine kleine Tastatur-Platine gebaut. Wichtig ist bei den Tastern nur, dass sie nicht prellen. Aber welcher Taster ist prellfrei? Deshalb kommt eine kleine aber durchaus effektive Schaltung zum Einsatz, die die Taster entprellen soll: <gallery> Bild:Nixie-Tasten-sch.gif|Stromlaufplan für die Tastatur Bild:Nixie-Tasten-auf.jpg|Leider habe ich das Board nach dem erstellen nicht gespeichert. Ein Foto tut's IMO auch ;) </gallery> Jetzt aber zum heikelsten Thema: der Taktgeber. Zum Testen der Uhr nahm ich mein DMM, das einen Taktausgang hat - aber auf Dauer ist ein klobiges, stromfressendes Multimeter keine Lösung für eine Uhr. Die erste Idee: ein Quarz-Oszillator. Ich hab doch mal was mit einem [http://www.national.com/ds/CD/CD4060BC.pdf CD4060] und einem 32,nochwas kHz-Quarz gelesen. Schnell das Datenblatt vom CD4060 überflogen... Das Teil sieht auf den ersten Blick recht gut aus, auf dem zweiten Blick sieht man, dass der höchste Teiler 214 ist. Bei dem 32,768kHz würde über den Teiler 2Hz herauskommen. Irgendwie muss man doch auf 1Hz kommen. Es liegen doch sicher noch ein paar CD4017 herum - die können doch zählen! Wenn man an einem CD4017 Q2 mit Reset verbindet, wird nach jeden zweiten Impuls an Q1 ein Takt ausgegeben. Das sollte funktionieren. Ein paar CD4060 und ein 32,768kHz-Quarz liegen gaaanz zufällig von der letzten Reichelt-Bestellung herum. Also schnell zum Testen mit 33pF-Kerkos einen Oszillator aufbauen... ..und: nix ist! Nur wenn ich mit dem DMM an Masse und Pin 9 messe, kommt hinten was halbwegs vernünftiges raus. Warum? Na, der Fehler sitzt natürlich davor! Ich habe natürlich das Datenblatt des CD4060 nur halb gelesen und Seite 4 übersehen, wo sich eine Schaltung für genau so eine Anwendung befindet. Laut Zeichnung sollte man einen 10pF und einen variablen Kondensator nehmen. Beides liegt nicht herum und ich war einen Tag vorher schon in meiner Elektro-"Apotheke". Ähnliche Werte sind da - also ein bisschen experimentieren. Irgendwann läuft der Quarz-Oszillator auch - aber naja, ein bisschen ungenau. Die Abweichung beträgt im Vergleich zur Funkuhr etwa 5s pro Minute. Okay, mich wundert's nicht, da ich ja alles andere als richtige Werte habe. Als ich die Leuchtstofflampe an meinem Werktisch abschalte bleibt plötzlich die Uhr stehen. Nichts geht mehr - $#!†. Also mal gucken, was die "Kollegen" so machen. CrappyThumb hat einen [http://pdfserv.maxim-ic.com/en/ds/DS1603.pdf DS1603], der eigentlich eine RTC ist, missbraucht und nutzt den Taktausgang für seine Uhr. Nachteil an dem IC: groß, teuer und schwer zu beschaffen. Rein "zufällig" habe ich zwei dieser ICs ergattern können. Pin 2-5 und 7 sind Masse, Pin 1 ist VDD und Pin 6 ist der Taktausgang. Wenn man den IC nun "normal" anschließt, gibt er noch keinen Takt aus. Um ihm nun einen Takt zu entlocken, muss er kurz (!!) verpolt angeschlossen werden (Strombegrenzung auf ein paar mA wäre hierbei angebracht). Der Timer hat eine Abweichung von ±2 Minuten pro Monat und ist somit schon recht genau. Wer auf extrem hohe Genauigkeit steht, kann nach einem DS32kHz Ausschau halten. Dies ist ein TCXO (=Temperaturkompensierter Quarzoszillator) und hat im Temperaturbereich zwischen 0 und +40°C eine Abweichung um ±1 Minute ''pro Jahr''! Bei konstanter Raumtemperatur dürfte die Genauigkeit noch deutlich höher sein. Wie schon der Name des ICs, gibt er einen Takt von 32kHz aus. Genauer: 32,768kHz - er kann somit direkt als Quarz-Ersatz an meine Schaltung angeschlossen werden: <gallery> Bild:Nixie-Takt-sch.gif Bild:Nixie-Takt-brd.gif </gallery> Durch kleine Veränderungen kann auch ein "normaler" Quarz angeschlossen werden. Eine weitere Methode um an einen 1Hz-Takt zu gelangen ist die Netzfrequenz. Auf lange Dauer macht das Sinn, für Sekundengenaue Anzeige ist allerdings nichts, da sie ständig etwas schwankt. <gallery> Bild:Nixie-Treiber-auf-vorne.jpg|Die Uhr in Urform von vorne Bild:Nixie-beta.jpg|Überblick über die ganze Uhr </gallery> [[Bild:Nixie-fertig.jpg|thumb|Die (äußerlich) fertige Nixie-Uhr]] Da die Uhr noch ein bisschen nackt ist, bekommt sie ein Holzgehäuse. Mit 110x110x110mm ist es recht knapp bemessen - die Elektronik passte gerade noch hinein. Die viel zu langen Flachbandkabel habe ich um die Uhrensteuerung gewickelt, damit es den Deckel nicht andauernd anhebt ;) Der Transformator für die 200V der Nixies kam gemeinsam mit der Spannungsstabilisierung unter eine Abdeckung (bestehend aus zerschnittenen CD-Hüllen). So ist die restliche Elektronik ein wenig vor der höheren Spannung geschützt. Eines stört mich aber noch an der Uhr. Am Tag kann man sie wegen der hellen Zahlen super ablesen, wenn man aber schlafen möchte, kann man nicht (zumindest ich), da das Teil das halbe Zimmer erhellt. Zeit ablesen ist auch nicht drin, da sich die Zahlen nicht deutlich genug abheben. Die Potis für die einzelnen Ziffern kann ich zwar herunterdrehen, dann sind die Ziffern jedoch gar nicht mehr zu sehen, da sie nur noch teilweise glimmen. Fahrtregler und ähnliche Motor-"dimmer" haben doch Pulsweitenmodulatoren eingebaut, das müsste man doch übertragen können!? Das menschliche Auge ist sowieso sehr träge und würde es nicht merken, wenn die Röhren vor sich hin "flackern". Also einen PWM mit dem NE555 aufbauen und schauen, wie es aussieht. Aber halt! Wie soll ich die Nixies schalten? Wenn ich die Anoden der Röhren mit einem MPSA42 schalte, habe ich knapp 200V auf der Logik, die sich dann mit einer Rauchwolke verabschieden würde... Also müssen die Kathoden der Röhren geschalten werden. Im Prinzip gibt es das gleiche Problem, da so wieder 200V auf meine 5V gelangen können. Naja, egal - zum Testen muss das Labor-Netzteil herhalten. Der PWM dimmt die Nixies zwar, das Ergebnis sieht aber ähnlich wie mit normalen Potentiometern aus. Irgendwie wundert es mich im Nachhinein auch nicht - die Schaltfrequenz war mit 10kHz viel zu hoch. Also auf etwa 1kHz heruntertrimmen und noch mal versuchen: Das Ergebnis sieht gut bis super aus. Auch bei sehr geringer Helligkeit werden die Zahlen wesentlich besser als mit den Potis angezeigt. Sogar der obere Teil der 5 glimmt perfekt. Vorher konnte ich dies nur mit sehr hohem Strom erreichen (was die Nixies nicht besonders lange mitmachen). Der PWM hat noch einen zweiten schönen Nebeneffekt: Die glimmenden Bereiche werden schärfer abgegrenzt und die Umgebung um die Filamente leuchten nicht mehr leicht bläulich :). Der Bau des Pulsweitenmodulators war somit in jeder Hinsicht lohnenswert. Der Haken an der Sache ist aber noch immer: Das Teil braucht eine galvanisch getrennte Stromversorgung. Ich hatte Glück und fand in meinem Pollin-Schrottsorti einen 5V DC-DC-Wandler - was aber für den Nachbau? Extra für den popeligen PWM einen stinkteueren DC-DC-Wandler oder einen Schaltregler verbauen? Das kann's doch nicht sein. Irgendwann in der Nacht fiel mir dann ein, dass nicht unbedingt die Stromversorgung getrennt sein muss, es kann doch auch der Signalausgang sein und dafür gibt es Optokoppler. Falls der Ausgang dann auch noch die Glimmspannung und den erforderlichen Strom aushalten, kann die Transistorstufe danach weggelassen werden. Die Schaltung sieht dann folgendermaßen aus: <gallery> Bild:Nixie-Dimm-sch.gif|Auf den Optionalen Teil kann verzichtet werden, wenn der Optokoppler den Nennstrom der Röhren abkann Nixie-Dimm-brd.gif|Die Platine wäre geätzt etwa 40x16mm groß. </gallery> Als ich den PWM samt DC-DC-Wandler anschloss und in die Uhr einbaute, zeigte sich ein "kleiner" Nachteil des Dimmers: Die Uhr zählt jetzt wieder wie bescheuert. Wenn ich auf den Sekunden-Taster drücke, bleibt sie allerdings ruhig. Irgendetwas muss also vor dem ODER (IC9B) nicht ganz stimmen. 100nF an Pin 5 gegen Masse und Ruhe war. Irgendwie scheint aber noch etwas an der Logik madig zu sein - Über Nacht fehlen oft einige Sekunden. Überprüfen, wo genau der Fehler nun steckt bzw. schauen, wo genau ein Signal unsauer ist, kann ich wegen fehlendem Oszi nicht. Vielleicht kann ich das mal bei meinem Bekannten oder in der Schule ausmessen (zum "fröhlichen Messen" hab ich leider nicht genug Hohlstunden). Zum Überprüfen der "verbuggten" Stellen war kein Oszi nötig. Ein wenig Intuition und ein paar mehr 1k-Widerstände halfen schon: - Pulldown an IC8 Pin 5 - Pulldown an SV9 Pin 1 Wenn die Uhr störungsfrei ohne Tastatur betrieben werden soll, Pulldowns an SV9 Pin 2-5 löten. Die EAGLE-Dateien gibt es selbstverständlich auch zum herunterladen: [[Bild:Nixie-Uhr.zip]]. == Nachtrag (09/2007) == Mittlerweile ist die Uhr leider kein zuverlässes Zeitanzeige-Werkzeug mehr. Irgendwo habe ich mich verlötet - das Ding weicht nach kurzer Zeit ziemlich vom Soll ab und die Überlegung steht nahe, ob ich die Uhr nicht einfach mit einem AVR und DCF-77-Empfänger aufwerte. Das Dimmen per PWM ist übrigens spitze, auch wenn mir damals in d.s.e. davon dringend abgeraten wurde (Lebensdauer der Röhren). Allerdings erfreuen sich die Nixies immernoch allerbester Leuchtkraft und werden es hoffentlich auch noch lange tun. 65e0e53801616e6a496a5197e9df62e53bc93623 46 45 2007-10-07T15:22:50Z Chris 2 wikitext text/x-wiki Vor ein paar Wochen fand ich eine schon etwas betagte Platine mit ein paar Nixie-Röhren. Also schnell fragen, ob die Platine noch gebraucht wird und freuen, dass es nicht der Fall ist! == Aber halt, stopp, Moment! Was sind überhaupt Nixies? == Nixies sind mit Neon gefüllte Röhren, in denen sich dünne, aus Blech ausgestanzte Ziffern befinden. Diese Ziffern sind mit feinen Drähtchen mit "der Außenwelt" verbunden. Um die feinen Plättchen befindet sich ein feines Gitter, die Anode. Nixies funktionieren nach dem gleichen Prinzip wie Glimmlämpchen, der Glimmentladung. Die Nixie-Röhren sind (fast) immer wie folgt aufgebaut: [[Bild:Nixie-Aufbau.gif]] Damit die Plättchen zum leuchten angeregt werden, müssen sie wie Glimmlämpchen mit Spannung versorgt werden - mit dem Unterschied, dass bei Nixies Gleichspannung verwendet wird, da sonst auch das Gitter leuchtet. Wichtig ist hier nur noch, dass die Spannung stimmt (meist um die 60-90V) und dass die Kathode an Masse liegt. Jetzt habe ich ungefähr erklärt wie Nixies aufgebaut sind und wie sie funktionieren - aber woher kommt der Name? Ende der 50er hat die Entwicklung der "numerischen Indikatoren" in der Firma Burroughs begonnen. Dort wurden sie unter dem Namen "<u>N</u>umeric <u>I</u>ndicator E<u>x</u>perimental No. <u>1</u>" als Patent angemeldet, In der Firma war der Kurzname der Anzeigen "NIX 1". Da es sich auch als Nixi liest, bürgerte sich der Name "Nixie" relativ schnell ein (nachzulesen unter [http://www.vcalc.net/display2.htm http://www.vcalc.net/display2.htm]). Jetzt wäre schon einmal geklärt, was Nixies sind. Aber was soll ich mit ihnen machen? Inspiriert durch Internetseiten wie [http://www.crappythumb.de.vu/ CrappyThumb] ist es schnell klar: Es wird eine Uhr gebaut! Als erstes werden die Röhren genauer unter die Lupe genommen - ich will ja wissen, ob alle noch funktionieren. [[Bild:Nixie-Roehre1.jpg|thumb|NEC 236 LD8007]] So sehen sie aus: NEC 236 LD8007 mit schon fast niedlicher Zeichenhöhe von 10mm. Sie können Zahlen von 0-9 sowie einen Punkt darstellen. Der große Vorteil an den Röh(ch)ren: Die Beine sind mit der Halterung 2,54mm auseinander. Die Beine sind genauso wie bei einem IC im DIP 14 Gehäuse angeordnet. [[Bild:Nixie-Roehre2.jpg|thumb|Test einer Röhre]] Um zu testen, ob die Nixies noch leuchten, oder schon so viel Luft gesaugt haben, dass das Neon schon zu wenig ist, dass sie leuchten, habe ich die einzelnen Röhren kurz an meine Plasmakugel gehalten. Wie du auf dem Foto siehst, leuchtet außer der 4 auch das Neon am Glaskolben. Dies kommt allerdings daher, dass das Neon durch die hohe Spannung am Glaskörper angeregt wird. Im späteren Betrieb sieht man das Leuchten selbstverständlich nicht mehr. Rechts in der Nixie ist ein blauer Streifen zu sehen - das ist der Sauerstoff, das die Röhre mit der Zeit gesaugt hat. Alle Nixies sind soweit ok, bis auf dass sie eine schon sehr hohe Zündspannung von 90V haben. Da kommt auch schon die nächste Frage: Wie mit einer Logik-Schaltung, die mit 5V arbeitet, 90V schalten? Treiber-ICs, die 100V und mehr schalten können kosten einiges und bei BC548 o. ä. ist bei 30V Schluss. Relais? Nein. Erstens sind die zu laut und zweitens zu teuer. Die Lösung kommt von [http://www.fairchildsemi.com/ Fairchild]! Der gefundene Transistor nennt sich [http://www.fairchildsemi.com/ds/MP/MPSA42.pdf MSPA42] und reicht dicke für die Anwendung. VCES=300V und IC=500mA. ...und Wunder, oh Wunder: Reichelt bietet die Transistoren für 9ct das Stück an. Meine Uhr hat 6 Stellen, 10 Zahlen: 60 Transistoren. Aber Stopp: Normalerweise geht doch eine Uhr nur bis 23:59:59. Sprich: wir brauchen nicht 60 MPSA42, sondern nur noch 45. Somit erspart man etwas Geld und Lötarbeit. Aber was, wenn ein Transistor stirbt und einen Kurzschluss zwischen Basis und Kollektor verursacht? Einen absoluten Schutz möchte ich nicht einbauen, aber ein bisschen sollte schon drin sein: Ein 47k-Widerstand an der Basis begrenzt den, im Schadensfall fließenden Strom, auf etwa 5mA. Die Logik sollte das ganze zumindest für kurze Zeit aushalten können. Also: EAGLE anwerfen - jetzt wird gezeichnet! <gallery> Bild:Nixie-Treiber-sch.gif|Stromlaufplan der Treiberplatine Bild:Nixie-Treiber-brd.gif|Die ungerouteten Signale werden mit 0,2mm dünnem Lackdraht verbunden. Bild:Nixie-Treiber-auf-hint.jpg|...und aufgebaut Bild:Nixie-Treiber-auf-unten.jpg|Nach einigen Stunden Fädeln war das gröbste geschafft Bild:Nixie-Treiber-auf-unten-draht.jpg|Einen Tag später sah die Platine dann so aus. </gallery> Die länglichen "Dinger" oben sind die Röhren (der Streifen darin ist die Anode [Gitter], die Punkte die jeweiligen Ziffern), die Kreise dazwischen kleine Glimmlämpchen. Die Widerstände haben alle den Wert 47k 1/4W und die Transistoren sind MPSA42. Die Wirepads habe ich zur Übersichtlichkeit hinzugefügt, später werden die Flachbandkabel direkt an den Widerständen angelötet. Die Anoden der einzelnen Nixies könnte zusammengefasst werden. Ich habe sie getrennt gelassen, da man somit die Helligkeit der einzelnen Röhren besser einstellen kann. [[Bild:Nixie-Dimm-alt.jpg|thumb|none]] Damit die Helligkeit der einzelnen Röhren verändert werden kann, verwende ich Potis, die zusätzlich 100k-Widerstände zur Strombegrenzung besitzen. Der Widerstand lässt sich somit zwischen 100 und 200kΩ regeln. Jetzt geht es zum ersten Testlauf - aber Moment: Woher die Spannung für die Nixies nehmen? Netzspannung wäre möglich, den Knall, der bei einer Fehlfunktion auftreten werden würde, möchte ich nicht miterleben. Strombegrenzung durch Lastwiderstand? Nein, eine Heizung will ich nicht unbedingt bauen... Ein kleiner Trenntrafo wäre es, liegt momentan aber nicht herum. Dafür aber zwei 9V-Transformatoren! Beide haben einen nicht gleichgerichteten Ausgang, also ideal für meine Anwendung: Der erste Transformator wandelt die Netzspannung in 9V um, der zweite wieder zurück nach ungefähr 200V. Der erste Transformator liefert gleichzeitig die Spannung für die Logik-Schaltung. Das schöne an der ganzen Sache: Der Strom vom zweiten Trafo ist begrenzt und der Trafo ist galvanisch getrennt, was bedeutet, dass man Kontakt zu beiden Ausgängen am Trafo (bzw. dahinter) haben muss, um einen Stromschlag zu bekommen. Wenn man es genau nimmt ist aber auch diese Lösung nicht unbedingt optimal, da zweimal einiges an Energie als Wärme an den Transformatoren "verloren" gehen. Eine bessere Lösung hierfür wäre ein Schaltregler. Mehr dazu später. Die Nixies leuchten prima, als ich eine der Glimmlampen anschließe gibt es allerdings einen blauen Funken und einen lauten Knall. Sch... Vorwiderstand vergessen! Also schnell noch einen Vorwiderstand einbauen und an den Trafo anschließen (mit an die Stromversorgung der Nixies - Gleichstrom. Deshalb leuchtet auch nur eine Elektrode) [[Bild:Nixie-Glimmdef.jpg|thumb|Eine Glimmlampe, nachdem sie ohne Vorwiderstand an 120V betrieben wurde]] Rechts sieht man, wie es aussieht, wenn man eine Glimmlampe erst ohne Vorwiderstand und danach mit richtigem Vorwiderstand an Gleichstrom betreibt. Unten in der Lampe sprang ein Funke über und machte die Elektrode an der Stelle dicht. Mit Wechselstrom und ein bisschen Geduld (um die halbe Stunde) erholte sich die gute wieder und leuchtet nun (fast) wie vorher. :) Damit ich die Schaltung testen kann, muss noch das Netzteil gebaut werden. Die ungefähr 200VAC vom zweiten Transformator müssen gleichgerichtet und ein bisschen geglättet werden, damit sie nicht flackern. Die Glättungselkos sollten aber nicht allzu groß ausfallen, da es bei einem Kurzschluss sonst mächtig knallen kann. Ich habe 2 22µF/160V in Reihe geschaltet. sie halten somit 320V aus und die Kapazität halbiert sich auf 11µF. Damit sich die Elkos nach dem Abschalten möglichst schnell entladen (da die Röhren nur ab 90V merklich Stromaufnahme haben). Dazu habe ich 3 3MΩ 1/4W-Widerstände parallel geschaltet. Der Widerstandswert drittelt sich, die Leistungen addieren sich. Die Widerstände verbraten bei 200V zwar "nur" 0,04W (sie würden knapp das 18-fache aushalten) aber "sischär is sischär" ;) Die 5V für die Steuerung kommt von einem 78(L)05, der in Standard-Beschaltung betrieben wird (Gleichrichten, Glätten, 7805, 100nF Kerko, 100µF Elko). [[Bild:Nixie-Strom.jpg|thumb|none|Das: links unten die Anschlüsse für die Nixies, rechts für die Logik. Bei den Elkos links sollte man vermeiden, beide Gehäuse gleichzeitig zu berühren, da dort doch einiges an Spannung anliegt.]] == Steuerung == Hier muss man überlegen, was die Uhr überhaupt machen muss. Die wohl wichtigere Frage dürfte aber vorerst sein "womit?". Zähler gibt es ja sehr viele. Binäre oder dezimale Zähler mit xyz Ausgängen. Was wir hier brauchen wäre ein 10-Stufiger Zähler mit dezimalem Ausgang. Der [http://www.national.com/ds/CD/CD4017BC.pdf CD4017] kann das und ist bei Reichelt recht günstig zu bekommen. Jede Stelle der Uhr bekommt einen CD4017. Das Carry-Out der Einer der Sekunden, Minuten und Stunden wird mit dem Takteingang der Zehner verbunden. So kann die Uhr schon einmal die Sekunden, Minuten und Stunden zweistellig nach oben Zählen. Wen das Wort "Carry-Out" irritiert: Es ist ein Übertrag, der gerade für einen solchen Verwendungszweck eingebaut wurde. Man könnte statt dem Carry-Out-Signal auch den Ausgang für die 0 verwenden, aber wenn es schon einen Übertrag gibt, muss man keinen Umweg gehen. So weit, so gut - aber wie bringt man die Uhr dazu, nach 59 Sekunden dazu, den Sekundenzähler wieder auf 0 zu setzen und die Minuten eines weiter zu zählen (Selbes natürlich bei den Minuten)? Na klar: 60 Sekunden dürfen nicht erreicht werden, deshalb kommt an den Ausgang 6 der Sekunden-Zehner eine Verbindung zum Reset des ICs und gleichzeitig eine Verbindung zum Takteingang der Minuten-Einer. Ja wunderbar, das sollte so klappen. Aber ein Tag hat eine "krumme" Anzahl von Stunden. Bei 20 oder 30 Uhr auf 0 umschalten ist nicht drin. Die Uhr soll bei 24:00:00 auf 00:00:00 umspringen. Sprich: Der Stunden-Zehner muss den Wert 2 haben und gleichzeitig der Stunden-Einer den Wert 4. Ein UND-Gatter ([http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT32_4.pdf 74HCT32]) muss her! That's it - die Uhr würde jetzt schon funktionieren. Wobei... die Uhr würde mit einem geeigneten Taktgeber richtig funktionieren. Aber wer schaltet die Uhr jedes mal um Mitternacht ein, wenn er sie stellen will? Einfach kurz 5V an die Takteingänge anschließen geht nicht, da die ganzen ICs bei Low auf Masse ziehen. Dioden würden funktionieren, wenn aber Low (also GND) an den Dioden anliegt, kommt hinten nicht GND heraus, sondern ein unbestimmtes Signal zwischen GND und 5V. Genau das sollte man vermeiden, da sonst irgendwann die Uhr verstellt wird. ODER-Gatter sind hierfür eine bessere Lösung. Die Ausgänge der ODER-Verknüpfungen werden an die Takteingänge der jeweiligen Zähler angeschlossen (nur die Einer), ein Eingang der einzelen ODER wird an den Übertrag vom letzten Zähler angeschlossen, der zweite Eingang kommt an eine Buchsenleiste. Damit man die Uhr bequemer stellen kann und nicht immer der blöde Taktgeber stört, muss der Taktgeber abschaltbar sein. Mit einer UND-Verknüpfung lässt sich das ganze einfach lösen. Damit der Takt des Taktgebers bei Low von dem Eingang Clockset durchschaltet, wird Clockset über einen BC548 und 1k-Widerstand invertiert. Von den restlichen UND- und ODER-Verknüpfungen werden die Eingänge auf Masse gelegt. Somit wird vermieden, dass sie zum schwingen anfangen und evtl. den Betrieb stören. <gallery> Bild:Nixie-Logik-sch.gif|Das "Gehirn" der Uhr. Die Teile sind jeweils für Stunden, Minuten und Sekunden zuständig Bild:Nixie-Logik-brd.gif|Was als Stromlaufplan harmlos aussieht, ist auf dem Board ziemlich heftig. Warum hat der CD4017 eigentlich keine geordneten Ausgänge? Bild:Nixie-Logik-auf-oben.jpg|Die unbestückte, ungelötete Platine von oben... Bild:Nixie-Logik-auf-unten.jpg|Wenn man hier einen Fehler hat: Viel Spaß beim Suchen. </gallery> Mit dem Multimeter als Taktgenerator konnte die Uhr jetzt an den Start gehen. Damit ich nicht einen ganzen Tag warten muss um zu sehen, ob die Uhr nun funktioniert oder nicht, habe ich eine relativ hohe Frequenz im S/O gewählt. Mit 4kHz schafft man einen Tag in knapp 22 Sekunden. Bei 10kHz sind es nur noch ~9s ;) Um die Zeit zu stellen, habe ich eine kleine Tastatur-Platine gebaut. Wichtig ist bei den Tastern nur, dass sie nicht prellen. Aber welcher Taster ist prellfrei? Deshalb kommt eine kleine aber durchaus effektive Schaltung zum Einsatz, die die Taster entprellen soll: <gallery> Bild:Nixie-Tasten-sch.gif|Stromlaufplan für die Tastatur Bild:Nixie-Tasten-auf.jpg|Leider habe ich das Board nach dem erstellen nicht gespeichert. Ein Foto tut's IMO auch ;) </gallery> Jetzt aber zum heikelsten Thema: der Taktgeber. Zum Testen der Uhr nahm ich mein DMM, das einen Taktausgang hat - aber auf Dauer ist ein klobiges, stromfressendes Multimeter keine Lösung für eine Uhr. Die erste Idee: ein Quarz-Oszillator. Ich hab doch mal was mit einem [http://www.national.com/ds/CD/CD4060BC.pdf CD4060] und einem 32,nochwas kHz-Quarz gelesen. Schnell das Datenblatt vom CD4060 überflogen... Das Teil sieht auf den ersten Blick recht gut aus, auf dem zweiten Blick sieht man, dass der höchste Teiler 214 ist. Bei dem 32,768kHz würde über den Teiler 2Hz herauskommen. Irgendwie muss man doch auf 1Hz kommen. Es liegen doch sicher noch ein paar CD4017 herum - die können doch zählen! Wenn man an einem CD4017 Q2 mit Reset verbindet, wird nach jeden zweiten Impuls an Q1 ein Takt ausgegeben. Das sollte funktionieren. Ein paar CD4060 und ein 32,768kHz-Quarz liegen gaaanz zufällig von der letzten Reichelt-Bestellung herum. Also schnell zum Testen mit 33pF-Kerkos einen Oszillator aufbauen... ..und: nix ist! Nur wenn ich mit dem DMM an Masse und Pin 9 messe, kommt hinten was halbwegs vernünftiges raus. Warum? Na, der Fehler sitzt natürlich davor! Ich habe natürlich das Datenblatt des CD4060 nur halb gelesen und Seite 4 übersehen, wo sich eine Schaltung für genau so eine Anwendung befindet. Laut Zeichnung sollte man einen 10pF und einen variablen Kondensator nehmen. Beides liegt nicht herum und ich war einen Tag vorher schon in meiner Elektro-"Apotheke". Ähnliche Werte sind da - also ein bisschen experimentieren. Irgendwann läuft der Quarz-Oszillator auch - aber naja, ein bisschen ungenau. Die Abweichung beträgt im Vergleich zur Funkuhr etwa 5s pro Minute. Okay, mich wundert's nicht, da ich ja alles andere als richtige Werte habe. Als ich die Leuchtstofflampe an meinem Werktisch abschalte bleibt plötzlich die Uhr stehen. Nichts geht mehr - $#!†. Also mal gucken, was die "Kollegen" so machen. CrappyThumb hat einen [http://pdfserv.maxim-ic.com/en/ds/DS1603.pdf DS1603], der eigentlich eine RTC ist, missbraucht und nutzt den Taktausgang für seine Uhr. Nachteil an dem IC: groß, teuer und schwer zu beschaffen. Rein "zufällig" habe ich zwei dieser ICs ergattern können. Pin 2-5 und 7 sind Masse, Pin 1 ist VDD und Pin 6 ist der Taktausgang. Wenn man den IC nun "normal" anschließt, gibt er noch keinen Takt aus. Um ihm nun einen Takt zu entlocken, muss er kurz (!!) verpolt angeschlossen werden (Strombegrenzung auf ein paar mA wäre hierbei angebracht). Der Timer hat eine Abweichung von ±2 Minuten pro Monat und ist somit schon recht genau. Wer auf extrem hohe Genauigkeit steht, kann nach einem DS32kHz Ausschau halten. Dies ist ein TCXO (=Temperaturkompensierter Quarzoszillator) und hat im Temperaturbereich zwischen 0 und +40°C eine Abweichung um ±1 Minute ''pro Jahr''! Bei konstanter Raumtemperatur dürfte die Genauigkeit noch deutlich höher sein. Wie schon der Name des ICs, gibt er einen Takt von 32kHz aus. Genauer: 32,768kHz - er kann somit direkt als Quarz-Ersatz an meine Schaltung angeschlossen werden: <gallery> Bild:Nixie-Takt-sch.gif Bild:Nixie-Takt-brd.gif </gallery> Durch kleine Veränderungen kann auch ein "normaler" Quarz angeschlossen werden. Eine weitere Methode um an einen 1Hz-Takt zu gelangen ist die Netzfrequenz. Auf lange Dauer macht das Sinn, für Sekundengenaue Anzeige ist allerdings nichts, da sie ständig etwas schwankt. <gallery> Bild:Nixie-Treiber-auf-vorne.jpg|Die Uhr in Urform von vorne Bild:Nixie-beta.jpg|Überblick über die ganze Uhr </gallery> [[Bild:Nixie-fertig.jpg|thumb|Die (äußerlich) fertige Nixie-Uhr]] Da die Uhr noch ein bisschen nackt ist, bekommt sie ein Holzgehäuse. Mit 110x110x110mm ist es recht knapp bemessen - die Elektronik passte gerade noch hinein. Die viel zu langen Flachbandkabel habe ich um die Uhrensteuerung gewickelt, damit es den Deckel nicht andauernd anhebt ;) Der Transformator für die 200V der Nixies kam gemeinsam mit der Spannungsstabilisierung unter eine Abdeckung (bestehend aus zerschnittenen CD-Hüllen). So ist die restliche Elektronik ein wenig vor der höheren Spannung geschützt. Eines stört mich aber noch an der Uhr. Am Tag kann man sie wegen der hellen Zahlen super ablesen, wenn man aber schlafen möchte, kann man nicht (zumindest ich), da das Teil das halbe Zimmer erhellt. Zeit ablesen ist auch nicht drin, da sich die Zahlen nicht deutlich genug abheben. Die Potis für die einzelnen Ziffern kann ich zwar herunterdrehen, dann sind die Ziffern jedoch gar nicht mehr zu sehen, da sie nur noch teilweise glimmen. Fahrtregler und ähnliche Motor-"dimmer" haben doch Pulsweitenmodulatoren eingebaut, das müsste man doch übertragen können!? Das menschliche Auge ist sowieso sehr träge und würde es nicht merken, wenn die Röhren vor sich hin "flackern". Also einen PWM mit dem NE555 aufbauen und schauen, wie es aussieht. Aber halt! Wie soll ich die Nixies schalten? Wenn ich die Anoden der Röhren mit einem MPSA42 schalte, habe ich knapp 200V auf der Logik, die sich dann mit einer Rauchwolke verabschieden würde... Also müssen die Kathoden der Röhren geschalten werden. Im Prinzip gibt es das gleiche Problem, da so wieder 200V auf meine 5V gelangen können. Naja, egal - zum Testen muss das Labor-Netzteil herhalten. Der PWM dimmt die Nixies zwar, das Ergebnis sieht aber ähnlich wie mit normalen Potentiometern aus. Irgendwie wundert es mich im Nachhinein auch nicht - die Schaltfrequenz war mit 10kHz viel zu hoch. Also auf etwa 1kHz heruntertrimmen und noch mal versuchen: Das Ergebnis sieht gut bis super aus. Auch bei sehr geringer Helligkeit werden die Zahlen wesentlich besser als mit den Potis angezeigt. Sogar der obere Teil der 5 glimmt perfekt. Vorher konnte ich dies nur mit sehr hohem Strom erreichen (was die Nixies nicht besonders lange mitmachen). Der PWM hat noch einen zweiten schönen Nebeneffekt: Die glimmenden Bereiche werden schärfer abgegrenzt und die Umgebung um die Filamente leuchten nicht mehr leicht bläulich :). Der Bau des Pulsweitenmodulators war somit in jeder Hinsicht lohnenswert. Der Haken an der Sache ist aber noch immer: Das Teil braucht eine galvanisch getrennte Stromversorgung. Ich hatte Glück und fand in meinem Pollin-Schrottsorti einen 5V DC-DC-Wandler - was aber für den Nachbau? Extra für den popeligen PWM einen stinkteueren DC-DC-Wandler oder einen Schaltregler verbauen? Das kann's doch nicht sein. Irgendwann in der Nacht fiel mir dann ein, dass nicht unbedingt die Stromversorgung getrennt sein muss, es kann doch auch der Signalausgang sein und dafür gibt es Optokoppler. Falls der Ausgang dann auch noch die Glimmspannung und den erforderlichen Strom aushalten, kann die Transistorstufe danach weggelassen werden. Die Schaltung sieht dann folgendermaßen aus: <gallery> Bild:Nixie-Dimm-sch.gif|Auf den Optionalen Teil kann verzichtet werden, wenn der Optokoppler den Nennstrom der Röhren abkann Bild:Nixie-Dimm-brd.gif|Die Platine wäre geätzt etwa 40x16mm groß. </gallery> Als ich den PWM samt DC-DC-Wandler anschloss und in die Uhr einbaute, zeigte sich ein "kleiner" Nachteil des Dimmers: Die Uhr zählt jetzt wieder wie bescheuert. Wenn ich auf den Sekunden-Taster drücke, bleibt sie allerdings ruhig. Irgendetwas muss also vor dem ODER (IC9B) nicht ganz stimmen. 100nF an Pin 5 gegen Masse und Ruhe war. Irgendwie scheint aber noch etwas an der Logik madig zu sein - Über Nacht fehlen oft einige Sekunden. Überprüfen, wo genau der Fehler nun steckt bzw. schauen, wo genau ein Signal unsauer ist, kann ich wegen fehlendem Oszi nicht. Vielleicht kann ich das mal bei meinem Bekannten oder in der Schule ausmessen (zum "fröhlichen Messen" hab ich leider nicht genug Hohlstunden). Zum Überprüfen der "verbuggten" Stellen war kein Oszi nötig. Ein wenig Intuition und ein paar mehr 1k-Widerstände halfen schon: - Pulldown an IC8 Pin 5 - Pulldown an SV9 Pin 1 Wenn die Uhr störungsfrei ohne Tastatur betrieben werden soll, Pulldowns an SV9 Pin 2-5 löten. Die EAGLE-Dateien gibt es selbstverständlich auch zum herunterladen: [[Bild:Nixie-Uhr.zip]]. == Nachtrag (09/2007) == Mittlerweile ist die Uhr leider kein zuverlässes Zeitanzeige-Werkzeug mehr. Irgendwo habe ich mich verlötet - das Ding weicht nach kurzer Zeit ziemlich vom Soll ab und die Überlegung steht nahe, ob ich die Uhr nicht einfach mit einem AVR und DCF-77-Empfänger aufwerte. Das Dimmen per PWM ist übrigens spitze, auch wenn mir damals in d.s.e. davon dringend abgeraten wurde (Lebensdauer der Röhren). Allerdings erfreuen sich die Nixies immernoch allerbester Leuchtkraft und werden es hoffentlich auch noch lange tun. [[Category:Elektronik]] e8b36ced6fb42ee67db9a3ccc4268cf3f4e85303 SNES-Joypad 0 35 47 2007-10-09T21:31:17Z Chris 2 noch nicht ganz fertig... wikitext text/x-wiki Als Kind hatte ich mir mal (ja, aus eigener Tasche) einen Super Nintendo gekauft. Nachdem er die Jahre leider nicht überlebt hat und ich doch ab und an mal ein bisschen Verlangen nach SNES habe, griff ich auf Emulatoren für den PC zurück. So gut die Programme auch sind - man hat ein Problem: man muss auf der Tastatur spielen. Das mag bei manchen Spielen noch gehen, wenn man jedoch in brenzliche Situationen kommt, braucht man dann doch die etwas trainierteren Daumen. Irgendwann kam ich auf die Idee, einfach das Gamepad an den PC anzuschließen. Mit einem Nachbau eines SNES-Gamepads, das ich mal geschenkt bekommen habe, funktionierte das ziemlich gut. Im Pad selbst waren zwei CD4021 (Schieberegister) verbaut. Die Funktionsweise des Gamepads ist somit genauso simpel wie... simpel. Wenn die CPU in der Konsole den Controller auslesen will, werden die Daten per Latch in das Register geladen, von wo es dann seriell ausgelesen werden kann. Die Beschaltung im Controller ist folgendermaßen: {| class="prettytable" ! Pin|| Farbe || Funktion |- | 1 || braun || GND |- | 2 || rot || Data |- | 3 || orange || Latch |- | 4 || gelb || Clock |- | 5 || weiß || Vcc |} Bei meiner ersten Entwicklung war das Gamepad am Parallel-Port angeschlossen und wurde von einem kleinen VB-Programm ausgelesen. Die Tastenanschläge wurden dann per DLL als Tastatur-Eingaben simuliert. Das ganze hatte nur ein paar Nachteile: * Die Software war nicht besonders schön * Der Parallelport wurde (mal wieder) zweckentfremdet * Man muss hinter den PC kriechen, wenn man wieder etwas drucken will * Das Ganze ist einfach nicht rund (vorangegangene Punkte) * Mein Notebook hat weder eine parallele noch serielle Schnittstelle Irgendwann entdeckte ich [http://www.obdev.at/products/avrusb/index.html AVR-USB], eine Software-Implementierung von USB in AVRs. Als Projekt war [http://www.raphnet.net/electronique/snes_nes_usb/index_en.php SNES/NES gamepad (and mouse) to USB adapter] verlinkt. [[Category:PC]] [[Category:AVR]] [[Category:USB]] Die Schaltung habe ich mir dann relativ zügig aufgebaut, um zu testen, ob da wirklich das dahintersteckt, was ich mir erwartet hatte. Tatsächlich meldete Windows 2s nach dem Einstecken der Konstruktion eine neue Hardware. Nur die Tatsache, dass an einem 28-Pin-Mikrocontroller nur ca. 10 Pins und auf den 8KB Speicher nur 3 belegt waren und das Ganze nicht richtig im Gamecontroller untergebracht werden konnte, störte mich ein wenig. Vor kurzem las ich dann folgendes auf obdev.at: <pre> New: Internal RC Oscillator Supported AVR-USB supports the internal RC oscillator of all AVRs with internal high frequency PLL, such as the ATTiny45 or ATTiny26. No external crystal is needed on these devices! See the EasyLogger example for details. </pre> Das war das, worauf ich gewartet hatte: Der ATTiny45 hat 8 Beine, wofür 2 für USB und weitere 3 für die Standardbeschaltung verwendet werden. Somit bleiben genau die benötigten drei Anschlüsse für das Gamepad frei. Die Beispielanwendung für die Impementierung ([http://www.obdev.at/products/avrusb/easylogger.html EasyLogger]) zielt schon sehr gut in die Richtung, in die ich gehen will. Der Großteil des Quelltextes konnte beibehalten werden, Teile kamen von Raph und wurden ziemlich stark umgebaut. Nachdem ich einige Wochen zuvor kläglich daran gescheitert bin, die Software von oben auf den ATTiny2313 zu portieren, nahm ich mir zum Ziel, den Quelltext so klein wie möglich zu gestalten. Nach etlichen Optimierversuchen und Brennvorgängen war es dann geschafft: Das kompilierte Programm ist exakt 2000 Byte groß. Leider hat der Device-Name etwas darunter gelitten - es ist allerdings noch deutlich erkennbar, worum es sich handelt. Ein weiteres Ziel war, die Elektronik im Controller unterzubringen, sodass nur noch ein USB-Kabel ohne weitere Elektronik am PC angeschlossen wird. 13e3281b51e06dc73d802ca2eec85ae68f693cac 53 47 2007-10-10T21:18:34Z Chris 2 fertig :) wikitext text/x-wiki Als Kind hatte ich mir mal (ja, aus eigener Tasche) einen Super Nintendo gekauft. Nachdem er die Jahre leider nicht überlebt hat und ich doch ab und an mal ein bisschen Verlangen nach SNES habe, griff ich auf Emulatoren für den PC zurück. So gut die Programme auch sind - man hat ein Problem: man muss auf der Tastatur spielen. Das mag bei manchen Spielen noch gehen, wenn man jedoch in brenzliche Situationen kommt, braucht man dann doch die etwas trainierteren Daumen. Irgendwann kam ich auf die Idee, einfach das Gamepad an den PC anzuschließen. Mit einem Nachbau eines SNES-Gamepads, das ich mal geschenkt bekommen habe, funktionierte das ziemlich gut. Im Pad selbst waren zwei CD4021 (Schieberegister) verbaut. Die Funktionsweise des Gamepads ist somit genauso simpel wie... simpel. Wenn die CPU in der Konsole den Controller auslesen will, werden die Daten per Latch in das Register geladen, von wo es dann seriell ausgelesen werden kann. [[Bild:SNES-stecker.jpg|thumb|Anschlussbelegung am Stecker]] Die Beschaltung im Controller ist folgendermaßen: {| ! Pin|| Farbe || Funktion |- | 1 || braun || GND |- | 2 || rot || Data |- | 3 || orange || Latch |- | 4 || gelb || Clock |- | 5 || weiß || Vcc |} Bei meiner ersten Entwicklung war das Gamepad am Parallel-Port angeschlossen und wurde von einem kleinen VB-Programm ausgelesen. Die Tastenanschläge wurden dann per DLL als Tastatur-Eingaben simuliert. Das ganze hatte nur ein paar Nachteile: * Die Software war nicht besonders schön * Der Parallelport wurde (mal wieder) zweckentfremdet * Man muss hinter den PC kriechen, wenn man wieder etwas drucken will * Das Ganze ist einfach nicht rund (vorangegangene Punkte) * Mein Notebook hat weder eine parallele noch serielle Schnittstelle Irgendwann entdeckte ich [http://www.obdev.at/products/avrusb/index.html AVR-USB], eine Software-Implementierung von USB in AVRs. Als Projekt war [http://www.raphnet.net/electronique/snes_nes_usb/index_en.php SNES/NES gamepad (and mouse) to USB adapter] verlinkt. Die Schaltung habe ich mir dann relativ zügig aufgebaut, um zu testen, ob da wirklich das dahintersteckt, was ich mir erwartet hatte. Tatsächlich meldete Windows 2s nach dem Einstecken der Konstruktion eine neue Hardware. Nur die Tatsache, dass an einem 28-Pin-Mikrocontroller nur ca. 10 Pins und auf den 8KB Speicher nur 3 belegt waren und das Ganze nicht richtig im Gamecontroller untergebracht werden konnte, störte mich ein wenig. Vor kurzem las ich dann folgendes auf obdev.at: <pre> New: Internal RC Oscillator Supported AVR-USB supports the internal RC oscillator of all AVRs with internal high frequency PLL, such as the ATTiny45 or ATTiny26. No external crystal is needed on these devices! See the EasyLogger example for details. </pre> Das war das, worauf ich gewartet hatte: Der ATTiny45 hat 8 Beine, wofür 2 für USB und weitere 3 für die Standardbeschaltung verwendet werden. Somit bleiben genau die benötigten drei Anschlüsse für das Gamepad frei. Die Beispielanwendung für die Impementierung ([http://www.obdev.at/products/avrusb/easylogger.html EasyLogger]) zielt schon sehr gut in die Richtung, in die ich gehen will. Der Großteil des Quelltextes konnte beibehalten werden, Teile kamen von Raph und wurden ziemlich stark umgebaut. Nachdem ich einige Wochen zuvor kläglich daran gescheitert bin, die Software von oben auf den ATTiny2313 zu portieren, nahm ich mir zum Ziel, den Quelltext so klein wie möglich zu gestalten. Nach etlichen Optimierversuchen und Brennvorgängen war es dann geschafft: Das kompilierte Programm ist exakt 2000 Byte groß. Leider hat der Device-Name etwas darunter gelitten - es ist allerdings noch deutlich erkennbar, worum es sich handelt. Ein weiteres Ziel war, die Elektronik im Controller unterzubringen, sodass nur noch ein USB-Kabel ohne weitere Elektronik am PC angeschlossen wird. Netterweise ist im Gamepad ziemlich viel Platz vorhanden, welcher erlaubt, selbst einen DIP-IC aufgelötet auf einer Platine zu fassen. Also flugs die Schaltung vom Steckbrett auf die Platine bringen. Nach dem ersten Test am PC war ich etwas irritiert: kein fröhliches "Plüm-Plim" vom PC, stattdessen kam nach einigen Wartesekunden ein "Plopp" aus den Lautsprechern: "Hardware wurde nicht erkannt". IC ausgelötet und wieder aufs Steckbrett: "Plüm-Plim" (Hardware erkannt). Auch nach langem Suchen war kein Fehler in der Schaltung zu finden. Also zurück an den Anfang: [[PLL im ATTiny45 kalibrieren]]. [[Bild:SNES-einbau.jpg|thumb|Einbau des AVR-USB-Controllers im SNES-Gamepad]] Nach ein paar Versuchen klappte es auch und ich konnte das Gamepad wieder schließen. Wenn mich jetzt die Lust packt heißt es nur noch Controller vorne am PC an einem freien USB-Port anschließen und losspielen. Da der Aufbau auf Lochraster zwar "ganz nett" ist, aber noch nicht der Weisheit letzter Schluss ist, habe eine kleine Schaltung + Platine in SMD in EAGLE erstellt: [[Bild:SNES-brd.png|thumb|none]] Die Schaltung ist zwar nicht gerade ideal zum Brennen des AVRs, aber evtl. könnte es klappen, wenn man die Anschlüsse für USB (oben) und für den SNES-Controllers (unten) ausnutzt. Leider kommt man nicht 'drum, einen Draht direkt an RESET zu löten. Platz für einen Testpin ist leider nicht mehr vorhanden. Die Anschlussbelegungen sind jeweils nach den Standards. Auf der SNES-Seite wie oben angegeben, auf USB-Seite so wie im USB-Standard angegeben (Näheres ist dem Stromlaufplan in der ZIP-Datei zu entnehmen). == Download == Die Firmware ist unkompiliert, da der OSCCAL-Wert nicht automatisch ermittelt wird. Weiterhin wurde kein Kompilat beigelegt, da das verwendete VID/PID-Paar (siehe usbconfig.h) nicht mir gehört und von jedem, der die Hardware einsetzt durch sein Paar ersetzt werden muss. (Wenn man die Schaltung für sich daheim privat betreibt, sollte es jedoch keine Probleme geben) [[Bild:SNES-USB.zip]] [[Category:PC]] [[Category:AVR]] [[Category:USB]] 6c5fa724766f73f79a51f045e9b80af5c5f90ff9 Datei:SNES-stecker.jpg 6 36 48 2007-10-10T20:49:23Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 49 48 2007-10-10T20:50:53Z Chris 2 Pinbelegung hinzugefügt wikitext text/x-wiki {| ! Pin|| Farbe || Funktion |- | 1 || braun || GND |- | 2 || rot || Data |- | 3 || orange || Latch |- | 4 || gelb || Clock |- | 5 || weiß || Vcc |} 5d2ec9c404d8853d0b8f83e067e034e42b09d1d8 Datei:SNES-einbau.jpg 6 37 50 2007-10-10T20:58:52Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:SNES-brd.png 6 38 51 2007-10-10T21:03:02Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:SNES-USB.zip 6 39 52 2007-10-10T21:12:04Z Chris 2 Firmware sowie EAGLE-Dateien Version 1.0 vom 10.10.2007 wikitext text/x-wiki Firmware sowie EAGLE-Dateien Version 1.0 vom 10.10.2007 e8ac42a226920783357430c51b6dece5a0510466 PLL im ATTiny45 kalibrieren 0 40 54 2007-10-10T21:23:18Z Chris 2 Seite erstellt - mehr nicht. wikitext text/x-wiki == Warum? == Die PLL im ATTiny45 muss bei manchen Anwendungen von 16MHz umkalibriert werden. Beispielsweise ist für AVR-USB ein Takt von möglichst genau 16.5MHz 2f212d8a5645242ee5c959ba42c675bad6549f49 55 54 2007-10-13T21:31:49Z Chris 2 erste Version wikitext text/x-wiki Der ATTiny 45 besitzt neben dem Tiny 26 eine interne PLL, die es erlaubt, den Takt vom AVR während dem Betrieb zu verändern. Standardmäßig ist diese auf 16MHz eingestellt, allerdings kann man deren Takt durch Verändern des OSCCAL-Registers verändern. == Warum? == Bei manchen Anwendungen ist ein Takt abseits von 16MHz erforderlich, wie zum Beispiel bei AVR-USB. Hier muss die Frequenz 16.5MHz betragen, da das Device vom PC sonst nicht erkannt wird. == AVR-USB == Im Beispiel [http://www.obdev.at/products/avrusb/easylogger.html EasyLogger] wird die abweichende Frequenz in main() berechnet, falls kein abweichender Wert im EEProm steht. Allerdings funktioniert die Errechnung nicht immer zuverlässig. Dann muss man den Wert manuell ermitteln. == Wert ermitteln == Man kann den OSCCAL-Wert natürlich per trial & error ermitteln, allerdings muss man (theoretisch) alle 256 Werte "durchprobieren". Wenn man vom festgelegten Registerwert ausgeht (lässt sich z. B. mit AVR Studio auslesen) kann man die Suche auf etwa 10-15 Werte beschränken. Allerdings ist das immernoch relativ Zeitaufwendig. Um die Sache zu erleichtern, bietet der ATTiny45 (wie eigentlich alle AVRs) die Funktion, den Takt auf einem Pin (PB4[?]) auszugeben. Dazu muss einfach die Fuse CKOUT aktiviert werden. Nun kann mit einem sehr simplen Programm und einem Frequenzzähler der CPU-Takt ermittelt werden: <pre> int main() { OSCCAL = 100; while(1); } </pre> Das Programm kann dann geflasht und der Takt an PB4 gemessen werden. Falls der Frequenzzähler (wie meiner) keine 16-20MHz mitmacht, kann die Fuse CKDIV8 (Takt durch 8 teilen) aktiviert werden. optional kann der Code auch dahingehend angepasst werden, dass er nicht mehrmals geflasht werden muss: <pre> int main() { DDRB &= ~(PB3) if(PINB | PB3) { OSCCAL = 150 } else { OSCCAL = 100; } while(1); } </pre> Wenn nun beim Anlegen der Spannung PB3 an Vcc anliegt, wird OSCCAL auf 150, andernfalls auf 100 gesetzt. Die Formel zum Berechnen des OSCCAL-Wertes lautet folgendermaßen: OSC<sub>ziel</sub> = (f<sub>max</sub>-f<sub>min</sub>)/(OSC<sub>max</sub>-OSC<sub>min</sub>)*(f<sub>ziel</sub>-OSC<sub>min</sub>)+f<sub>min</sub> Angenommen, bei OSCCAL 100 werden 15.5MHz gemessen und bei OSCCAL 150 eine Frequenz von 17.86MHz und die Zielfrequenz 16.5MHz beträgt, ergibt sich folgendes: OSC<sub>ziel</sub> = (17.86-15.5)/(150-100)*(16.5-100)+15.5 OSC<sub>ziel</sub> = 11.56 Der Wert für OSCCAL ist dann 12. Dieser Wert kann entweder an die erste Stelle im EEProm oder direkt ins Programm geschrieben werden. == Aber Vorsicht! == Beim Portieren von Schaltungen vom Steckbrett auf Lochraster/Platine kann es sein, dass man den AVR neu kalibrieren muss! Das führte beim [[SNES-Joypad]] ein bisschen zu Verwirrung, da die Schaltung auf dem Steckbrett aber auf der Platine nicht mehr vom PC erkannt wurde. Sobald ich wieder einen Tiny45 zum Basteln über habe, werde ich evtl. ein USB-Device bauen, das man direkt kalibrieren kann und der Wert direkt vom PC ausgelesen werden kann. ef7b718a94216a2a77239ab431d9a5adf8fddedf PLL im ATTiny45 kalibrieren 0 40 56 55 2007-10-13T21:38:28Z Chris 2 Kategorie hinzugefügt wikitext text/x-wiki Der ATTiny 45 besitzt neben dem Tiny 26 eine interne PLL, die es erlaubt, den Takt vom AVR während dem Betrieb zu verändern. Standardmäßig ist diese auf 16MHz eingestellt, allerdings kann man deren Takt durch Verändern des OSCCAL-Registers verändern. == Warum? == Bei manchen Anwendungen ist ein Takt abseits von 16MHz erforderlich, wie zum Beispiel bei AVR-USB. Hier muss die Frequenz 16.5MHz betragen, da das Device vom PC sonst nicht erkannt wird. == AVR-USB == Im Beispiel [http://www.obdev.at/products/avrusb/easylogger.html EasyLogger] wird die abweichende Frequenz in main() berechnet, falls kein abweichender Wert im EEProm steht. Allerdings funktioniert die Errechnung nicht immer zuverlässig. Dann muss man den Wert manuell ermitteln. == Wert ermitteln == Man kann den OSCCAL-Wert natürlich per trial & error ermitteln, allerdings muss man (theoretisch) alle 256 Werte "durchprobieren". Wenn man vom festgelegten Registerwert ausgeht (lässt sich z. B. mit AVR Studio auslesen) kann man die Suche auf etwa 10-15 Werte beschränken. Allerdings ist das immernoch relativ Zeitaufwendig. Um die Sache zu erleichtern, bietet der ATTiny45 (wie eigentlich alle AVRs) die Funktion, den Takt auf einem Pin (PB4[?]) auszugeben. Dazu muss einfach die Fuse CKOUT aktiviert werden. Nun kann mit einem sehr simplen Programm und einem Frequenzzähler der CPU-Takt ermittelt werden: <pre> int main() { OSCCAL = 100; while(1); } </pre> Das Programm kann dann geflasht und der Takt an PB4 gemessen werden. Falls der Frequenzzähler (wie meiner) keine 16-20MHz mitmacht, kann die Fuse CKDIV8 (Takt durch 8 teilen) aktiviert werden. optional kann der Code auch dahingehend angepasst werden, dass er nicht mehrmals geflasht werden muss: <pre> int main() { DDRB &= ~(PB3) if(PINB | PB3) { OSCCAL = 150 } else { OSCCAL = 100; } while(1); } </pre> Wenn nun beim Anlegen der Spannung PB3 an Vcc anliegt, wird OSCCAL auf 150, andernfalls auf 100 gesetzt. Die Formel zum Berechnen des OSCCAL-Wertes lautet folgendermaßen: OSC<sub>ziel</sub> = (f<sub>max</sub>-f<sub>min</sub>)/(OSC<sub>max</sub>-OSC<sub>min</sub>)*(f<sub>ziel</sub>-OSC<sub>min</sub>)+f<sub>min</sub> Angenommen, bei OSCCAL 100 werden 15.5MHz gemessen und bei OSCCAL 150 eine Frequenz von 17.86MHz und die Zielfrequenz 16.5MHz beträgt, ergibt sich folgendes: OSC<sub>ziel</sub> = (17.86-15.5)/(150-100)*(16.5-100)+15.5 OSC<sub>ziel</sub> = 11.56 Der Wert für OSCCAL ist dann 12. Dieser Wert kann entweder an die erste Stelle im EEProm oder direkt ins Programm geschrieben werden. == Aber Vorsicht! == Beim Portieren von Schaltungen vom Steckbrett auf Lochraster/Platine kann es sein, dass man den AVR neu kalibrieren muss! Das führte beim [[SNES-Joypad]] ein bisschen zu Verwirrung, da die Schaltung auf dem Steckbrett aber auf der Platine nicht mehr vom PC erkannt wurde. Sobald ich wieder einen Tiny45 zum Basteln über habe, werde ich evtl. ein USB-Device bauen, das man direkt kalibrieren kann und der Wert direkt vom PC ausgelesen werden kann. [[Category:AVR]] [[Category:USB]] 42190fc24928446d52f100e865af37fb17d1639f Datei:AVR-Doper-auf.jpg 6 41 57 2007-10-13T21:59:41Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:AVR-Doper-brd.png 6 42 58 2007-10-13T22:01:02Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:AVR-Doper.zip 6 43 59 2007-10-13T22:09:46Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 AVR-Doper 0 44 60 2007-10-13T22:12:59Z Chris 2 Die Seite wurde neu angelegt: Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [[http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper]] ins Auge. Mein bis dahin aktu... wikitext text/x-wiki Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [[http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper]] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Ich habe auch damit angefangen, eine SMD-Version der Platine zu machen, allerdings gibt es ein paar Platzprobleme (der ATMega in TQFP ist einfach zu klein für die ganzen Bauteile außen herum). Die Firmware wurde nicht verwendet und kann direkt auf der [[http://www.obdev.at/products/avrusb/avrdoper.html Projektseite]] heruntergeladen werden Download ded optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] [[Category:AVR]] [[Category:USB]] [[Category:PC]] 48b90379ab7c727797bc42ee5ee7328e3bab2ef2 61 60 2007-10-17T10:39:19Z Chris 2 Schönheitskorrektur Links wikitext text/x-wiki Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Ich habe auch damit angefangen, eine SMD-Version der Platine zu machen, allerdings gibt es ein paar Platzprobleme (der ATMega in TQFP ist einfach zu klein für die ganzen Bauteile außen herum). Die Firmware wurde nicht verwendet und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download ded optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] [[Category:AVR]] [[Category:USB]] [[Category:PC]] 0ed9b92c9a0236ce2f23aab443b759c52691dc3c 332 61 2009-07-01T10:41:52Z Chris 2 wikitext text/x-wiki Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Ich habe auch damit angefangen, eine SMD-Version der Platine zu machen, allerdings gibt es ein paar Platzprobleme (der ATMega in TQFP ist einfach zu klein für die ganzen Bauteile außen herum). Die Firmware wurde nicht verändert und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download ded optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] [[Category:AVR]] [[Category:USB]] [[Category:PC]] 66ea1349adcd5f2898aa0395bda7493737f4946b 341 332 2009-07-05T21:29:14Z Chris 2 wikitext text/x-wiki Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Ich habe auch damit angefangen, eine SMD-Version der Platine zu machen, allerdings gibt es ein paar Platzprobleme (der ATMega in TQFP ist einfach zu klein für die ganzen Bauteile außen herum). Die Firmware wurde nicht verändert und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download des optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] [[Category:AVR]] [[Category:USB]] [[Category:PC]] 31299ee45d258f61c1f0e5c9cb737a5d68c88e74 Benutzer:Chris 2 45 63 2007-11-16T18:00:53Z Chris 2 Die Seite wurde neu angelegt: Tjo, das ist es also, mein ganz privater Bereich auf Hobbyelektronik.org. Ich bin Chris und quasi der Schöpfer von der Homepage hier. Irgendwann in diesem Jahrhunder... wikitext text/x-wiki Tjo, das ist es also, mein ganz privater Bereich auf Hobbyelektronik.org. Ich bin Chris und quasi der Schöpfer von der Homepage hier. Irgendwann in diesem Jahrhundert (lt. Archive.org Ende 2003) fing ich damit an, meine mehr oder weniger gelungenen Bastel-Projekte auf hobby-elektronik.de.vu zu veröffentlichen. Damals noch bei Tripod. Der Speicherplatz wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich irgendwann, auf das schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10 April 2005 die Domain hobbyelektronik.org gekauft. Zu .org kam es, da mir eine Woche davor jemand die .net-Domain "geklaut" hat. Im Nachhinein bin ich glücklich um diesen Zustand - damit bin ich/sind wir dem .NET-Hype vollkommen entgangen. Eine richtige Organisation sind wir zwar noch immer nicht aber das kann ja noch werden ;) Momentan werde ich Fachinformatiker/Anwendungsentwicklung und bin auf dem Endspurt. Weiter verfüge ich über die fachgebundene Hochschulreife und werde nicht davor zurückschrecken, auf sie zurückzugreifen (wenn ich eine gute Firma für's duale Studium finde). == Hobbies == * Elektronik ** Digitales (analoge Schaltungen sind mir irgendwie unheimlich *g*) ** Alles, das irgendwas anzeigt ** AVRs ** Sensoren ** Interfaces (v. a. zum PC) * Programmieren (in dieser Reihenfolge) ** C# ** C (für AVRs) f40bcd2c10c0813e37c42a350ac1f361e226b5e6 309 63 2008-11-02T21:08:28Z Chris 2 dies und das wikitext text/x-wiki Tjo, das ist es also, mein ganz privater Bereich auf Hobbyelektronik.org. Ich bin Chris und quasi der Schöpfer von der Homepage hier. Irgendwann in diesem Jahrhundert (lt. Archive.org Ende 2003) fing ich damit an, meine mehr oder weniger gelungenen Bastel-Projekte auf hobby-elektronik.de.vu zu veröffentlichen. Damals noch bei Tripod. Der Speicherplatz wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich irgendwann, auf das schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10 April 2005 die Domain hobbyelektronik.org gekauft. Zu .org kam es, da mir eine Woche davor jemand die .net-Domain "geklaut" hat. Im Nachhinein bin ich glücklich um diesen Zustand - damit bin ich/sind wir dem .NET-Hype vollkommen entgangen. Eine richtige Organisation sind wir zwar noch immer nicht aber das kann ja noch werden ;) Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" (oder so ähnlich) schimpfen. Alles weitere steht im [http://hobbyelektronik.org/b/ Blog] (detaillierte Verlinkung kommt, sobald es etwas zu verlinken gibt). == Hobbies == * Elektronik ** Digitales (analoge Schaltungen sind mir irgendwie unheimlich *g*) ** Alles, das irgendwas anzeigt ** AVRs ** Sensoren ** Interfaces (v. a. zum PC) * Programmieren ** C# ** PHP ** JavaScript (mit allem Drum und Dran) ** C (für AVRs) 5a31bbbba7f8b23cc151bf7692917fd35e718700 MediaWiki:Sidebar 8 8 64 15 2007-12-11T22:12:41Z Qsysopr 1 wikitext text/x-wiki * navigation ** mainpage|mainpage ** portal-url|portal ** currentevents-url|currentevents ** recentchanges-url|recentchanges ** randompage-url|randompage ** Spezial:Alle_Seiten|Alle Seiten * Bereiche ** Category:Elektronik|Elektronik (ohne µC) ** Category:AVR|AVR ** Category:PC|am PC ** Category:Software|Software (PC) ** Category:LCD|LCDs ** Category:Maschinen|Maschinen ** Category:Sonstiges|Sonstiges ** Category:Murks|Murks 3770c6ec7c55b9c198fb623af19645aa47c4acc4 Hobbyelektronik.org:Impressum 4 4 68 8 2008-01-05T10:11:30Z Chris 2 ICQ-Link von Robert korrigiert wikitext text/x-wiki == Hauptverantwortlicher<br> == [[Benutzer:Chris|Christof Rueß]]<br>St.-Wendelin-Str. 9<br>89264 Weißenhorn<br>E-Mail: chris at hobbyelektronik punkt org<br>ICQ: [http://www.icq.com/people/about_me.php?uin=176979879 176979879] == Mitwirkende == [[Benutzer:Robert|Robert Obermayer]]<br>E-Mail: robert at hobbyelektronik punkt org<br>ICQ: [http://www.icq.com/people/about_me.php?uin=78202589 78202589] == Kontakt == Wenn du Fragen an uns hast, lies bitte zuerst nochmal die Seite, zu der du die Frage hast und dann evtl. nochmal die [[FAQ]].<br>Am einfachsten und am unkompliziertesten ist der Kontakt per E-Mail.<br>Um Spams ein bisschen einzuschränken, dürftest du auf der Homepage hier keine klickbaren Links finden. Wie man an die Adresse kommt, muss (so denke ich) nicht erklärt werden. Weiterhin habe wir einen [[#hobbyelektronik|IRC-Channel]], der von uns auch relativ stark genutzt wird und auch internationales Publikum (ok, ein Schwede) hat. Einfach mal vorbeischauen: [irc://irc.quakenet.eu.org/hobbyelektronik #hobbyelektronik @ Quakenet] <br> Bitte beachte auch die Seite [[Hobbyelektronik.org:Über Hobbyelektronik.org|Über Hobbyelektronik.org]], auf der insbesondere der Haftungsausschluss zu beachten ist! 65e2619be87f2c6a0631196ee12d1699ad053269 Nixie-Uhr 0 34 72 46 2008-03-01T21:40:29Z Chris 2 Link auf CrappyThumb korrigiert (Danke an die schwachmaten, die crappythumb.de.vu auf gulli umgeleitet haben) wikitext text/x-wiki Vor ein paar Wochen fand ich eine schon etwas betagte Platine mit ein paar Nixie-Röhren. Also schnell fragen, ob die Platine noch gebraucht wird und freuen, dass es nicht der Fall ist! == Aber halt, stopp, Moment! Was sind überhaupt Nixies? == Nixies sind mit Neon gefüllte Röhren, in denen sich dünne, aus Blech ausgestanzte Ziffern befinden. Diese Ziffern sind mit feinen Drähtchen mit "der Außenwelt" verbunden. Um die feinen Plättchen befindet sich ein feines Gitter, die Anode. Nixies funktionieren nach dem gleichen Prinzip wie Glimmlämpchen, der Glimmentladung. Die Nixie-Röhren sind (fast) immer wie folgt aufgebaut: [[Bild:Nixie-Aufbau.gif]] Damit die Plättchen zum leuchten angeregt werden, müssen sie wie Glimmlämpchen mit Spannung versorgt werden - mit dem Unterschied, dass bei Nixies Gleichspannung verwendet wird, da sonst auch das Gitter leuchtet. Wichtig ist hier nur noch, dass die Spannung stimmt (meist um die 60-90V) und dass die Kathode an Masse liegt. Jetzt habe ich ungefähr erklärt wie Nixies aufgebaut sind und wie sie funktionieren - aber woher kommt der Name? Ende der 50er hat die Entwicklung der "numerischen Indikatoren" in der Firma Burroughs begonnen. Dort wurden sie unter dem Namen "<u>N</u>umeric <u>I</u>ndicator E<u>x</u>perimental No. <u>1</u>" als Patent angemeldet, In der Firma war der Kurzname der Anzeigen "NIX 1". Da es sich auch als Nixi liest, bürgerte sich der Name "Nixie" relativ schnell ein (nachzulesen unter [http://www.vcalc.net/display2.htm http://www.vcalc.net/display2.htm]). Jetzt wäre schon einmal geklärt, was Nixies sind. Aber was soll ich mit ihnen machen? Inspiriert durch Internetseiten wie [http://www-users.rwth-aachen.de/Hannes.Nordmann/hp2/index2.htm CrappyThumb] ist es schnell klar: Es wird eine Uhr gebaut! Als erstes werden die Röhren genauer unter die Lupe genommen - ich will ja wissen, ob alle noch funktionieren. [[Bild:Nixie-Roehre1.jpg|thumb|NEC 236 LD8007]] So sehen sie aus: NEC 236 LD8007 mit schon fast niedlicher Zeichenhöhe von 10mm. Sie können Zahlen von 0-9 sowie einen Punkt darstellen. Der große Vorteil an den Röh(ch)ren: Die Beine sind mit der Halterung 2,54mm auseinander. Die Beine sind genauso wie bei einem IC im DIP 14 Gehäuse angeordnet. [[Bild:Nixie-Roehre2.jpg|thumb|Test einer Röhre]] Um zu testen, ob die Nixies noch leuchten, oder schon so viel Luft gesaugt haben, dass das Neon schon zu wenig ist, dass sie leuchten, habe ich die einzelnen Röhren kurz an meine Plasmakugel gehalten. Wie du auf dem Foto siehst, leuchtet außer der 4 auch das Neon am Glaskolben. Dies kommt allerdings daher, dass das Neon durch die hohe Spannung am Glaskörper angeregt wird. Im späteren Betrieb sieht man das Leuchten selbstverständlich nicht mehr. Rechts in der Nixie ist ein blauer Streifen zu sehen - das ist der Sauerstoff, das die Röhre mit der Zeit gesaugt hat. Alle Nixies sind soweit ok, bis auf dass sie eine schon sehr hohe Zündspannung von 90V haben. Da kommt auch schon die nächste Frage: Wie mit einer Logik-Schaltung, die mit 5V arbeitet, 90V schalten? Treiber-ICs, die 100V und mehr schalten können kosten einiges und bei BC548 o. ä. ist bei 30V Schluss. Relais? Nein. Erstens sind die zu laut und zweitens zu teuer. Die Lösung kommt von [http://www.fairchildsemi.com/ Fairchild]! Der gefundene Transistor nennt sich [http://www.fairchildsemi.com/ds/MP/MPSA42.pdf MSPA42] und reicht dicke für die Anwendung. VCES=300V und IC=500mA. ...und Wunder, oh Wunder: Reichelt bietet die Transistoren für 9ct das Stück an. Meine Uhr hat 6 Stellen, 10 Zahlen: 60 Transistoren. Aber Stopp: Normalerweise geht doch eine Uhr nur bis 23:59:59. Sprich: wir brauchen nicht 60 MPSA42, sondern nur noch 45. Somit erspart man etwas Geld und Lötarbeit. Aber was, wenn ein Transistor stirbt und einen Kurzschluss zwischen Basis und Kollektor verursacht? Einen absoluten Schutz möchte ich nicht einbauen, aber ein bisschen sollte schon drin sein: Ein 47k-Widerstand an der Basis begrenzt den, im Schadensfall fließenden Strom, auf etwa 5mA. Die Logik sollte das ganze zumindest für kurze Zeit aushalten können. Also: EAGLE anwerfen - jetzt wird gezeichnet! <gallery> Bild:Nixie-Treiber-sch.gif|Stromlaufplan der Treiberplatine Bild:Nixie-Treiber-brd.gif|Die ungerouteten Signale werden mit 0,2mm dünnem Lackdraht verbunden. Bild:Nixie-Treiber-auf-hint.jpg|...und aufgebaut Bild:Nixie-Treiber-auf-unten.jpg|Nach einigen Stunden Fädeln war das gröbste geschafft Bild:Nixie-Treiber-auf-unten-draht.jpg|Einen Tag später sah die Platine dann so aus. </gallery> Die länglichen "Dinger" oben sind die Röhren (der Streifen darin ist die Anode [Gitter], die Punkte die jeweiligen Ziffern), die Kreise dazwischen kleine Glimmlämpchen. Die Widerstände haben alle den Wert 47k 1/4W und die Transistoren sind MPSA42. Die Wirepads habe ich zur Übersichtlichkeit hinzugefügt, später werden die Flachbandkabel direkt an den Widerständen angelötet. Die Anoden der einzelnen Nixies könnte zusammengefasst werden. Ich habe sie getrennt gelassen, da man somit die Helligkeit der einzelnen Röhren besser einstellen kann. [[Bild:Nixie-Dimm-alt.jpg|thumb|none]] Damit die Helligkeit der einzelnen Röhren verändert werden kann, verwende ich Potis, die zusätzlich 100k-Widerstände zur Strombegrenzung besitzen. Der Widerstand lässt sich somit zwischen 100 und 200kΩ regeln. Jetzt geht es zum ersten Testlauf - aber Moment: Woher die Spannung für die Nixies nehmen? Netzspannung wäre möglich, den Knall, der bei einer Fehlfunktion auftreten werden würde, möchte ich nicht miterleben. Strombegrenzung durch Lastwiderstand? Nein, eine Heizung will ich nicht unbedingt bauen... Ein kleiner Trenntrafo wäre es, liegt momentan aber nicht herum. Dafür aber zwei 9V-Transformatoren! Beide haben einen nicht gleichgerichteten Ausgang, also ideal für meine Anwendung: Der erste Transformator wandelt die Netzspannung in 9V um, der zweite wieder zurück nach ungefähr 200V. Der erste Transformator liefert gleichzeitig die Spannung für die Logik-Schaltung. Das schöne an der ganzen Sache: Der Strom vom zweiten Trafo ist begrenzt und der Trafo ist galvanisch getrennt, was bedeutet, dass man Kontakt zu beiden Ausgängen am Trafo (bzw. dahinter) haben muss, um einen Stromschlag zu bekommen. Wenn man es genau nimmt ist aber auch diese Lösung nicht unbedingt optimal, da zweimal einiges an Energie als Wärme an den Transformatoren "verloren" gehen. Eine bessere Lösung hierfür wäre ein Schaltregler. Mehr dazu später. Die Nixies leuchten prima, als ich eine der Glimmlampen anschließe gibt es allerdings einen blauen Funken und einen lauten Knall. Sch... Vorwiderstand vergessen! Also schnell noch einen Vorwiderstand einbauen und an den Trafo anschließen (mit an die Stromversorgung der Nixies - Gleichstrom. Deshalb leuchtet auch nur eine Elektrode) [[Bild:Nixie-Glimmdef.jpg|thumb|Eine Glimmlampe, nachdem sie ohne Vorwiderstand an 120V betrieben wurde]] Rechts sieht man, wie es aussieht, wenn man eine Glimmlampe erst ohne Vorwiderstand und danach mit richtigem Vorwiderstand an Gleichstrom betreibt. Unten in der Lampe sprang ein Funke über und machte die Elektrode an der Stelle dicht. Mit Wechselstrom und ein bisschen Geduld (um die halbe Stunde) erholte sich die gute wieder und leuchtet nun (fast) wie vorher. :) Damit ich die Schaltung testen kann, muss noch das Netzteil gebaut werden. Die ungefähr 200VAC vom zweiten Transformator müssen gleichgerichtet und ein bisschen geglättet werden, damit sie nicht flackern. Die Glättungselkos sollten aber nicht allzu groß ausfallen, da es bei einem Kurzschluss sonst mächtig knallen kann. Ich habe 2 22µF/160V in Reihe geschaltet. sie halten somit 320V aus und die Kapazität halbiert sich auf 11µF. Damit sich die Elkos nach dem Abschalten möglichst schnell entladen (da die Röhren nur ab 90V merklich Stromaufnahme haben). Dazu habe ich 3 3MΩ 1/4W-Widerstände parallel geschaltet. Der Widerstandswert drittelt sich, die Leistungen addieren sich. Die Widerstände verbraten bei 200V zwar "nur" 0,04W (sie würden knapp das 18-fache aushalten) aber "sischär is sischär" ;) Die 5V für die Steuerung kommt von einem 78(L)05, der in Standard-Beschaltung betrieben wird (Gleichrichten, Glätten, 7805, 100nF Kerko, 100µF Elko). [[Bild:Nixie-Strom.jpg|thumb|none|Das: links unten die Anschlüsse für die Nixies, rechts für die Logik. Bei den Elkos links sollte man vermeiden, beide Gehäuse gleichzeitig zu berühren, da dort doch einiges an Spannung anliegt.]] == Steuerung == Hier muss man überlegen, was die Uhr überhaupt machen muss. Die wohl wichtigere Frage dürfte aber vorerst sein "womit?". Zähler gibt es ja sehr viele. Binäre oder dezimale Zähler mit xyz Ausgängen. Was wir hier brauchen wäre ein 10-Stufiger Zähler mit dezimalem Ausgang. Der [http://www.national.com/ds/CD/CD4017BC.pdf CD4017] kann das und ist bei Reichelt recht günstig zu bekommen. Jede Stelle der Uhr bekommt einen CD4017. Das Carry-Out der Einer der Sekunden, Minuten und Stunden wird mit dem Takteingang der Zehner verbunden. So kann die Uhr schon einmal die Sekunden, Minuten und Stunden zweistellig nach oben Zählen. Wen das Wort "Carry-Out" irritiert: Es ist ein Übertrag, der gerade für einen solchen Verwendungszweck eingebaut wurde. Man könnte statt dem Carry-Out-Signal auch den Ausgang für die 0 verwenden, aber wenn es schon einen Übertrag gibt, muss man keinen Umweg gehen. So weit, so gut - aber wie bringt man die Uhr dazu, nach 59 Sekunden dazu, den Sekundenzähler wieder auf 0 zu setzen und die Minuten eines weiter zu zählen (Selbes natürlich bei den Minuten)? Na klar: 60 Sekunden dürfen nicht erreicht werden, deshalb kommt an den Ausgang 6 der Sekunden-Zehner eine Verbindung zum Reset des ICs und gleichzeitig eine Verbindung zum Takteingang der Minuten-Einer. Ja wunderbar, das sollte so klappen. Aber ein Tag hat eine "krumme" Anzahl von Stunden. Bei 20 oder 30 Uhr auf 0 umschalten ist nicht drin. Die Uhr soll bei 24:00:00 auf 00:00:00 umspringen. Sprich: Der Stunden-Zehner muss den Wert 2 haben und gleichzeitig der Stunden-Einer den Wert 4. Ein UND-Gatter ([http://www.semiconductors.philips.com/acrobat/datasheets/74HC_HCT32_4.pdf 74HCT32]) muss her! That's it - die Uhr würde jetzt schon funktionieren. Wobei... die Uhr würde mit einem geeigneten Taktgeber richtig funktionieren. Aber wer schaltet die Uhr jedes mal um Mitternacht ein, wenn er sie stellen will? Einfach kurz 5V an die Takteingänge anschließen geht nicht, da die ganzen ICs bei Low auf Masse ziehen. Dioden würden funktionieren, wenn aber Low (also GND) an den Dioden anliegt, kommt hinten nicht GND heraus, sondern ein unbestimmtes Signal zwischen GND und 5V. Genau das sollte man vermeiden, da sonst irgendwann die Uhr verstellt wird. ODER-Gatter sind hierfür eine bessere Lösung. Die Ausgänge der ODER-Verknüpfungen werden an die Takteingänge der jeweiligen Zähler angeschlossen (nur die Einer), ein Eingang der einzelen ODER wird an den Übertrag vom letzten Zähler angeschlossen, der zweite Eingang kommt an eine Buchsenleiste. Damit man die Uhr bequemer stellen kann und nicht immer der blöde Taktgeber stört, muss der Taktgeber abschaltbar sein. Mit einer UND-Verknüpfung lässt sich das ganze einfach lösen. Damit der Takt des Taktgebers bei Low von dem Eingang Clockset durchschaltet, wird Clockset über einen BC548 und 1k-Widerstand invertiert. Von den restlichen UND- und ODER-Verknüpfungen werden die Eingänge auf Masse gelegt. Somit wird vermieden, dass sie zum schwingen anfangen und evtl. den Betrieb stören. <gallery> Bild:Nixie-Logik-sch.gif|Das "Gehirn" der Uhr. Die Teile sind jeweils für Stunden, Minuten und Sekunden zuständig Bild:Nixie-Logik-brd.gif|Was als Stromlaufplan harmlos aussieht, ist auf dem Board ziemlich heftig. Warum hat der CD4017 eigentlich keine geordneten Ausgänge? Bild:Nixie-Logik-auf-oben.jpg|Die unbestückte, ungelötete Platine von oben... Bild:Nixie-Logik-auf-unten.jpg|Wenn man hier einen Fehler hat: Viel Spaß beim Suchen. </gallery> Mit dem Multimeter als Taktgenerator konnte die Uhr jetzt an den Start gehen. Damit ich nicht einen ganzen Tag warten muss um zu sehen, ob die Uhr nun funktioniert oder nicht, habe ich eine relativ hohe Frequenz im S/O gewählt. Mit 4kHz schafft man einen Tag in knapp 22 Sekunden. Bei 10kHz sind es nur noch ~9s ;) Um die Zeit zu stellen, habe ich eine kleine Tastatur-Platine gebaut. Wichtig ist bei den Tastern nur, dass sie nicht prellen. Aber welcher Taster ist prellfrei? Deshalb kommt eine kleine aber durchaus effektive Schaltung zum Einsatz, die die Taster entprellen soll: <gallery> Bild:Nixie-Tasten-sch.gif|Stromlaufplan für die Tastatur Bild:Nixie-Tasten-auf.jpg|Leider habe ich das Board nach dem erstellen nicht gespeichert. Ein Foto tut's IMO auch ;) </gallery> Jetzt aber zum heikelsten Thema: der Taktgeber. Zum Testen der Uhr nahm ich mein DMM, das einen Taktausgang hat - aber auf Dauer ist ein klobiges, stromfressendes Multimeter keine Lösung für eine Uhr. Die erste Idee: ein Quarz-Oszillator. Ich hab doch mal was mit einem [http://www.national.com/ds/CD/CD4060BC.pdf CD4060] und einem 32,nochwas kHz-Quarz gelesen. Schnell das Datenblatt vom CD4060 überflogen... Das Teil sieht auf den ersten Blick recht gut aus, auf dem zweiten Blick sieht man, dass der höchste Teiler 214 ist. Bei dem 32,768kHz würde über den Teiler 2Hz herauskommen. Irgendwie muss man doch auf 1Hz kommen. Es liegen doch sicher noch ein paar CD4017 herum - die können doch zählen! Wenn man an einem CD4017 Q2 mit Reset verbindet, wird nach jeden zweiten Impuls an Q1 ein Takt ausgegeben. Das sollte funktionieren. Ein paar CD4060 und ein 32,768kHz-Quarz liegen gaaanz zufällig von der letzten Reichelt-Bestellung herum. Also schnell zum Testen mit 33pF-Kerkos einen Oszillator aufbauen... ..und: nix ist! Nur wenn ich mit dem DMM an Masse und Pin 9 messe, kommt hinten was halbwegs vernünftiges raus. Warum? Na, der Fehler sitzt natürlich davor! Ich habe natürlich das Datenblatt des CD4060 nur halb gelesen und Seite 4 übersehen, wo sich eine Schaltung für genau so eine Anwendung befindet. Laut Zeichnung sollte man einen 10pF und einen variablen Kondensator nehmen. Beides liegt nicht herum und ich war einen Tag vorher schon in meiner Elektro-"Apotheke". Ähnliche Werte sind da - also ein bisschen experimentieren. Irgendwann läuft der Quarz-Oszillator auch - aber naja, ein bisschen ungenau. Die Abweichung beträgt im Vergleich zur Funkuhr etwa 5s pro Minute. Okay, mich wundert's nicht, da ich ja alles andere als richtige Werte habe. Als ich die Leuchtstofflampe an meinem Werktisch abschalte bleibt plötzlich die Uhr stehen. Nichts geht mehr - $#!†. Also mal gucken, was die "Kollegen" so machen. CrappyThumb hat einen [http://pdfserv.maxim-ic.com/en/ds/DS1603.pdf DS1603], der eigentlich eine RTC ist, missbraucht und nutzt den Taktausgang für seine Uhr. Nachteil an dem IC: groß, teuer und schwer zu beschaffen. Rein "zufällig" habe ich zwei dieser ICs ergattern können. Pin 2-5 und 7 sind Masse, Pin 1 ist VDD und Pin 6 ist der Taktausgang. Wenn man den IC nun "normal" anschließt, gibt er noch keinen Takt aus. Um ihm nun einen Takt zu entlocken, muss er kurz (!!) verpolt angeschlossen werden (Strombegrenzung auf ein paar mA wäre hierbei angebracht). Der Timer hat eine Abweichung von ±2 Minuten pro Monat und ist somit schon recht genau. Wer auf extrem hohe Genauigkeit steht, kann nach einem DS32kHz Ausschau halten. Dies ist ein TCXO (=Temperaturkompensierter Quarzoszillator) und hat im Temperaturbereich zwischen 0 und +40°C eine Abweichung um ±1 Minute ''pro Jahr''! Bei konstanter Raumtemperatur dürfte die Genauigkeit noch deutlich höher sein. Wie schon der Name des ICs, gibt er einen Takt von 32kHz aus. Genauer: 32,768kHz - er kann somit direkt als Quarz-Ersatz an meine Schaltung angeschlossen werden: <gallery> Bild:Nixie-Takt-sch.gif Bild:Nixie-Takt-brd.gif </gallery> Durch kleine Veränderungen kann auch ein "normaler" Quarz angeschlossen werden. Eine weitere Methode um an einen 1Hz-Takt zu gelangen ist die Netzfrequenz. Auf lange Dauer macht das Sinn, für Sekundengenaue Anzeige ist allerdings nichts, da sie ständig etwas schwankt. <gallery> Bild:Nixie-Treiber-auf-vorne.jpg|Die Uhr in Urform von vorne Bild:Nixie-beta.jpg|Überblick über die ganze Uhr </gallery> [[Bild:Nixie-fertig.jpg|thumb|Die (äußerlich) fertige Nixie-Uhr]] Da die Uhr noch ein bisschen nackt ist, bekommt sie ein Holzgehäuse. Mit 110x110x110mm ist es recht knapp bemessen - die Elektronik passte gerade noch hinein. Die viel zu langen Flachbandkabel habe ich um die Uhrensteuerung gewickelt, damit es den Deckel nicht andauernd anhebt ;) Der Transformator für die 200V der Nixies kam gemeinsam mit der Spannungsstabilisierung unter eine Abdeckung (bestehend aus zerschnittenen CD-Hüllen). So ist die restliche Elektronik ein wenig vor der höheren Spannung geschützt. Eines stört mich aber noch an der Uhr. Am Tag kann man sie wegen der hellen Zahlen super ablesen, wenn man aber schlafen möchte, kann man nicht (zumindest ich), da das Teil das halbe Zimmer erhellt. Zeit ablesen ist auch nicht drin, da sich die Zahlen nicht deutlich genug abheben. Die Potis für die einzelnen Ziffern kann ich zwar herunterdrehen, dann sind die Ziffern jedoch gar nicht mehr zu sehen, da sie nur noch teilweise glimmen. Fahrtregler und ähnliche Motor-"dimmer" haben doch Pulsweitenmodulatoren eingebaut, das müsste man doch übertragen können!? Das menschliche Auge ist sowieso sehr träge und würde es nicht merken, wenn die Röhren vor sich hin "flackern". Also einen PWM mit dem NE555 aufbauen und schauen, wie es aussieht. Aber halt! Wie soll ich die Nixies schalten? Wenn ich die Anoden der Röhren mit einem MPSA42 schalte, habe ich knapp 200V auf der Logik, die sich dann mit einer Rauchwolke verabschieden würde... Also müssen die Kathoden der Röhren geschalten werden. Im Prinzip gibt es das gleiche Problem, da so wieder 200V auf meine 5V gelangen können. Naja, egal - zum Testen muss das Labor-Netzteil herhalten. Der PWM dimmt die Nixies zwar, das Ergebnis sieht aber ähnlich wie mit normalen Potentiometern aus. Irgendwie wundert es mich im Nachhinein auch nicht - die Schaltfrequenz war mit 10kHz viel zu hoch. Also auf etwa 1kHz heruntertrimmen und noch mal versuchen: Das Ergebnis sieht gut bis super aus. Auch bei sehr geringer Helligkeit werden die Zahlen wesentlich besser als mit den Potis angezeigt. Sogar der obere Teil der 5 glimmt perfekt. Vorher konnte ich dies nur mit sehr hohem Strom erreichen (was die Nixies nicht besonders lange mitmachen). Der PWM hat noch einen zweiten schönen Nebeneffekt: Die glimmenden Bereiche werden schärfer abgegrenzt und die Umgebung um die Filamente leuchten nicht mehr leicht bläulich :). Der Bau des Pulsweitenmodulators war somit in jeder Hinsicht lohnenswert. Der Haken an der Sache ist aber noch immer: Das Teil braucht eine galvanisch getrennte Stromversorgung. Ich hatte Glück und fand in meinem Pollin-Schrottsorti einen 5V DC-DC-Wandler - was aber für den Nachbau? Extra für den popeligen PWM einen stinkteueren DC-DC-Wandler oder einen Schaltregler verbauen? Das kann's doch nicht sein. Irgendwann in der Nacht fiel mir dann ein, dass nicht unbedingt die Stromversorgung getrennt sein muss, es kann doch auch der Signalausgang sein und dafür gibt es Optokoppler. Falls der Ausgang dann auch noch die Glimmspannung und den erforderlichen Strom aushalten, kann die Transistorstufe danach weggelassen werden. Die Schaltung sieht dann folgendermaßen aus: <gallery> Bild:Nixie-Dimm-sch.gif|Auf den Optionalen Teil kann verzichtet werden, wenn der Optokoppler den Nennstrom der Röhren abkann Bild:Nixie-Dimm-brd.gif|Die Platine wäre geätzt etwa 40x16mm groß. </gallery> Als ich den PWM samt DC-DC-Wandler anschloss und in die Uhr einbaute, zeigte sich ein "kleiner" Nachteil des Dimmers: Die Uhr zählt jetzt wieder wie bescheuert. Wenn ich auf den Sekunden-Taster drücke, bleibt sie allerdings ruhig. Irgendetwas muss also vor dem ODER (IC9B) nicht ganz stimmen. 100nF an Pin 5 gegen Masse und Ruhe war. Irgendwie scheint aber noch etwas an der Logik madig zu sein - Über Nacht fehlen oft einige Sekunden. Überprüfen, wo genau der Fehler nun steckt bzw. schauen, wo genau ein Signal unsauer ist, kann ich wegen fehlendem Oszi nicht. Vielleicht kann ich das mal bei meinem Bekannten oder in der Schule ausmessen (zum "fröhlichen Messen" hab ich leider nicht genug Hohlstunden). Zum Überprüfen der "verbuggten" Stellen war kein Oszi nötig. Ein wenig Intuition und ein paar mehr 1k-Widerstände halfen schon: - Pulldown an IC8 Pin 5 - Pulldown an SV9 Pin 1 Wenn die Uhr störungsfrei ohne Tastatur betrieben werden soll, Pulldowns an SV9 Pin 2-5 löten. Die EAGLE-Dateien gibt es selbstverständlich auch zum herunterladen: [[Bild:Nixie-Uhr.zip]]. == Nachtrag (09/2007) == Mittlerweile ist die Uhr leider kein zuverlässes Zeitanzeige-Werkzeug mehr. Irgendwo habe ich mich verlötet - das Ding weicht nach kurzer Zeit ziemlich vom Soll ab und die Überlegung steht nahe, ob ich die Uhr nicht einfach mit einem AVR und DCF-77-Empfänger aufwerte. Das Dimmen per PWM ist übrigens spitze, auch wenn mir damals in d.s.e. davon dringend abgeraten wurde (Lebensdauer der Röhren). Allerdings erfreuen sich die Nixies immernoch allerbester Leuchtkraft und werden es hoffentlich auch noch lange tun. [[Category:Elektronik]] 2a85c6ace9c5db57c97dd2e3d431b5d3e285c529 Datei:Resizepics.zip 6 62 280 2008-08-07T20:55:16Z Chris 2 http://hobbyelektronik.org/wiki/index.php?title=Image_Resizer wikitext text/x-wiki http://hobbyelektronik.org/wiki/index.php?title=Image_Resizer d63d783985246841acd738b8ffd60cb6bbc9fa64 Image Resizer 0 63 281 2008-08-07T21:06:43Z Chris 2 Seite erstellt wikitext text/x-wiki ==Ausgangssituation== Eine bekannte mit mäßigen Kenntnissen in Bildbearbeitung möchte in regelmäßigen Zeitabständen Bilder auf ihre Homepage hochladen. ==Problem== Die Bilder von der Digitalkamera sind groß und die Internetverbindung langsam. Also müssen sie in zwei Hinsichten verkleinert werden: Bildgröße und Dateigröße. ==Lösung== PHP war schon öfter der schnelle (und v.a. dreckige) Weg zum Erfolg. Also habe ich Teile meines schon etwas in die Tage gekommenen [http://hobbyelektronik.org/fotos Foto-Albums] verwertet und ein kleines Script erstellt, das die Arbeit übernimmt. Damit die gute Frau die Bilder nicht auf meinen Webserver hochladen muss um sie dann kleiner wieder zu bekommen (hirnrissig, siehe Problem), soll das ganze auf dem eigenen PC laufen - ohne Webserver. PHP bietet von sich aus ein CLI (Commandline-Interface) an, dafür braucht man allerdings trotzdem alle PHP-bezogenen Dateien. Ungut, weil man etwas falsch machen kann... Dank Bambalam und seinem Compiler/Embedder [http://www.bambalam.se/bamcompile/ Bamcompile] kann man aus PHP-Scripts selbstständig lauffähige EXE-Dateien erstellen - sogar mit Extensions! Also habe ich das Script etwas mehr auf CLI angepasst und mit Bamcompile zur Executable verarbeitet. ==Verwendung== Einfach Bilddateien (JPG, GIF, PNG) auf resize.exe ziehen und schon wird verkleinert. Die verkleinerten Bilder werden im gleichen Ordner erstellt und ihnen wird ein "_sm" angehängt, aus IMG_1234.JPG wird also IMG_1234_sm.JPG Achtung: bestehende Dateien mit diesem Namen werden ohne Rückfrage überschrieben Momentan wird die lange Kante des Bildes auf 1600 Pixel verkleinert, das Seitenverhältnis bleibt gleich. Bei JPEG wird standardmäßig eine Qualitätsstufe von 90% verwendet. Beide Werte können in der resize.php ganz oben verändert werden, danach muss sie aber neu kompiliert werden. Ich habe einige Testbilder (ok 10 Megapixel) um sage und schreibe 90% komprimieren können. ==Download== [http://hobbyelektronik.org/wiki/index.php/Bild:Resizepics.zip Resizepics.zip] (1,2MB) Nach dem Download muss nur noch die ZIP dekomprimiert werden und einmal compile.bat ausgeführt werden (die EXE liegt aus Platzgründen nicht dabei, dafür der Compiler) 1567efe3bcbfef696e223e3124b880eef80fd594 282 281 2008-08-07T21:08:52Z Chris 2 Kategorie hinzugefügt wikitext text/x-wiki ==Ausgangssituation== Eine bekannte mit mäßigen Kenntnissen in Bildbearbeitung möchte in regelmäßigen Zeitabständen Bilder auf ihre Homepage hochladen. ==Problem== Die Bilder von der Digitalkamera sind groß und die Internetverbindung langsam. Also müssen sie in zwei Hinsichten verkleinert werden: Bildgröße und Dateigröße. ==Lösung== PHP war schon öfter der schnelle (und v.a. dreckige) Weg zum Erfolg. Also habe ich Teile meines schon etwas in die Tage gekommenen [http://hobbyelektronik.org/fotos Foto-Albums] verwertet und ein kleines Script erstellt, das die Arbeit übernimmt. Damit die gute Frau die Bilder nicht auf meinen Webserver hochladen muss um sie dann kleiner wieder zu bekommen (hirnrissig, siehe Problem), soll das ganze auf dem eigenen PC laufen - ohne Webserver. PHP bietet von sich aus ein CLI (Commandline-Interface) an, dafür braucht man allerdings trotzdem alle PHP-bezogenen Dateien. Ungut, weil man etwas falsch machen kann... Dank Bambalam und seinem Compiler/Embedder [http://www.bambalam.se/bamcompile/ Bamcompile] kann man aus PHP-Scripts selbstständig lauffähige EXE-Dateien erstellen - sogar mit Extensions! Also habe ich das Script etwas mehr auf CLI angepasst und mit Bamcompile zur Executable verarbeitet. ==Verwendung== Einfach Bilddateien (JPG, GIF, PNG) auf resize.exe ziehen und schon wird verkleinert. Die verkleinerten Bilder werden im gleichen Ordner erstellt und ihnen wird ein "_sm" angehängt, aus IMG_1234.JPG wird also IMG_1234_sm.JPG Achtung: bestehende Dateien mit diesem Namen werden ohne Rückfrage überschrieben Momentan wird die lange Kante des Bildes auf 1600 Pixel verkleinert, das Seitenverhältnis bleibt gleich. Bei JPEG wird standardmäßig eine Qualitätsstufe von 90% verwendet. Beide Werte können in der resize.php ganz oben verändert werden, danach muss sie aber neu kompiliert werden. Ich habe einige Testbilder (ok 10 Megapixel) um sage und schreibe 90% komprimieren können. ==Download== [http://hobbyelektronik.org/wiki/index.php/Bild:Resizepics.zip Resizepics.zip] (1,2MB) Nach dem Download muss nur noch die ZIP dekomprimiert werden und einmal compile.bat ausgeführt werden (die EXE liegt aus Platzgründen nicht dabei, dafür der Compiler) [[Category:Software (PC)]] a06c81ac88338d7ac5ac483de238399d09af880d 283 282 2008-08-07T21:09:52Z Chris 2 Kategorie korrigiert (bin doof) wikitext text/x-wiki ==Ausgangssituation== Eine bekannte mit mäßigen Kenntnissen in Bildbearbeitung möchte in regelmäßigen Zeitabständen Bilder auf ihre Homepage hochladen. ==Problem== Die Bilder von der Digitalkamera sind groß und die Internetverbindung langsam. Also müssen sie in zwei Hinsichten verkleinert werden: Bildgröße und Dateigröße. ==Lösung== PHP war schon öfter der schnelle (und v.a. dreckige) Weg zum Erfolg. Also habe ich Teile meines schon etwas in die Tage gekommenen [http://hobbyelektronik.org/fotos Foto-Albums] verwertet und ein kleines Script erstellt, das die Arbeit übernimmt. Damit die gute Frau die Bilder nicht auf meinen Webserver hochladen muss um sie dann kleiner wieder zu bekommen (hirnrissig, siehe Problem), soll das ganze auf dem eigenen PC laufen - ohne Webserver. PHP bietet von sich aus ein CLI (Commandline-Interface) an, dafür braucht man allerdings trotzdem alle PHP-bezogenen Dateien. Ungut, weil man etwas falsch machen kann... Dank Bambalam und seinem Compiler/Embedder [http://www.bambalam.se/bamcompile/ Bamcompile] kann man aus PHP-Scripts selbstständig lauffähige EXE-Dateien erstellen - sogar mit Extensions! Also habe ich das Script etwas mehr auf CLI angepasst und mit Bamcompile zur Executable verarbeitet. ==Verwendung== Einfach Bilddateien (JPG, GIF, PNG) auf resize.exe ziehen und schon wird verkleinert. Die verkleinerten Bilder werden im gleichen Ordner erstellt und ihnen wird ein "_sm" angehängt, aus IMG_1234.JPG wird also IMG_1234_sm.JPG Achtung: bestehende Dateien mit diesem Namen werden ohne Rückfrage überschrieben Momentan wird die lange Kante des Bildes auf 1600 Pixel verkleinert, das Seitenverhältnis bleibt gleich. Bei JPEG wird standardmäßig eine Qualitätsstufe von 90% verwendet. Beide Werte können in der resize.php ganz oben verändert werden, danach muss sie aber neu kompiliert werden. Ich habe einige Testbilder (ok 10 Megapixel) um sage und schreibe 90% komprimieren können. ==Download== [http://hobbyelektronik.org/wiki/index.php/Bild:Resizepics.zip Resizepics.zip] (1,2MB) Nach dem Download muss nur noch die ZIP dekomprimiert werden und einmal compile.bat ausgeführt werden (die EXE liegt aus Platzgründen nicht dabei, dafür der Compiler) [[Category:Software]] b82fadb4023766e9b0c95213efc5fb986a04ba8f Diskussion:Hauptseite 1 61 289 2008-08-09T21:40:14Z Chris 2 Die Seite wurde geleert. wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 295 289 2008-08-09T21:58:03Z Qsysopr 1 Schützte „[[Diskussion:Hauptseite]]“: andauernder Vandalismus [edit=autoconfirmed:move=autoconfirmed] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 296 295 2008-08-09T21:58:44Z Qsysopr 1 Neuer Abschnitt /* Bis auf weiteres gesperrt */ wikitext text/x-wiki == Bis auf weiteres gesperrt == Wegen dem andauernden Spam ist diese Diskussionsseite bis auf weiteres gesperrt 5a1ed736f01ee80e63cca7c532f4aae5269744cc Datei:Cursors.png 6 64 290 2008-08-09T21:41:17Z Chris 2 Cursor vom Cursorset ;) wikitext text/x-wiki Cursor vom Cursorset ;) 76f0f9cddad1bf185740e9fab28435c84f1811af Datei:Cursors.zip 6 65 291 2008-08-09T21:50:55Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Cursor 0 66 292 2008-08-09T21:52:44Z Chris 2 Die Seite wurde neu angelegt: Vor knapp zwei Jahren hingen mir die Standard Windows-Cursor zum Hals raus. Da hat man endlich einen schönen Monitor auf dem Tisch stehen und muss dann einen verpixel... wikitext text/x-wiki Vor knapp zwei Jahren hingen mir die Standard Windows-Cursor zum Hals raus. Da hat man endlich einen schönen Monitor auf dem Tisch stehen und muss dann einen verpixelten Cursor anschauen. Also habe ich die wichtigsten Cursor nachgemalt - folgendes kam dabei heraus: [[Bild:Cursors.png]] Als "Goodie" noch ein schönes Overlay-Icon für Verknüpfungen. Das Icon kann man mit [http://www.microsoft.com/windowsxp/Downloads/powertoys/Xppowertoys.mspx Tweak UI] (Explorer -> Shortcut -> Button "Change") abändern. Die Cursor kann man in den Systemsteuerungen setzen. ==Bekannte Probleme== Windows XP bzw. manche Grafikkarten machen bei der Alpha-Transparenz ein wenig Ärger. Bei ATi-Grafikkarten haben die Cursor bei Video-Overlays einen schwarzen Saum, bei nVidia-Karten werden zusätzliche Icons neben dem Cursor (z. B. "+" beim Drag & Drop-Kopieren von Dateien) nicht dargestellt. Ferner gibt es in RealVNC leichte Darstellungsprobleme. Über diese kleinen Fehler kann man meiner Meinung jedoch hinweg sehen ;) ==Download== [[Bild:Cursors.zip]] [[Category:Sonstiges]] a42bbbcc76f7fa30e6a5bde49cf8cda92468730f Hauptseite 0 1 293 11 2008-08-09T21:55:42Z Chris 2 Neues wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. ==Neues== 09.08.2008 [[Cursor]] 08.08.2008 [[Image Resizer]] 9282a704e18d116c17d75086222d8be5e7f02c3d 294 293 2008-08-09T21:56:39Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. ==Neues== 09.08.2008 [[Cursor]] 08.08.2008 [[Image Resizer]] 14.03.2008 [[Platinenbohrmaschine]] 8b9cfe4095fb4a3e8cde34adf0fed0f26b266711 307 294 2008-09-01T17:09:03Z Robert 3 /* Neues */ wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. ==Neues== 01.09.2008 [[Labornetzteil]] 09.08.2008 [[Cursor]] 08.08.2008 [[Image Resizer]] 14.03.2008 [[Platinenbohrmaschine]] 7876d62d1205e75fc0a888cd46edc24bd8e47e78 323 307 2009-01-19T22:21:00Z Chris 2 Datenlogger hinzugefügt wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. ==Neues== 19.01.2009 [[Datenlogger]] 01.09.2008 [[Labornetzteil]] 09.08.2008 [[Cursor]] 08.08.2008 [[Image Resizer]] 14.03.2008 [[Platinenbohrmaschine]] 6c9480b3125391e5d0b11db19b405f0b7cf6553d 338 323 2009-07-03T22:23:41Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. ==Neues== 04.07.2009 [[Touchlight]] 19.01.2009 [[Datenlogger]] 01.09.2008 [[Labornetzteil]] 09.08.2008 [[Cursor]] 08.08.2008 [[Image Resizer]] 14.03.2008 [[Platinenbohrmaschine]] 97a94fd8103ced0dad93b1288d3f319a014d9b82 Datenlogger 0 76 310 2008-11-06T22:28:54Z Chris 2 Artikel erstellt wikitext text/x-wiki Diese Seite soll die Entstehung (und irgendwann mal die fertige Software) eines Datenloggers beschreiben. == Geschichte == Ursprung dieses Projekts ist irgendwann zwischen 2006 und 2007. [[Benutzer:Robert|Robert]] hatte die Idee bzw. den Bedarf nach einem Logger, um über längeren Zeitraum irgendetwas zu messen. Daraus entstand ein schönes Stück Hardware mit einem ADS8344 (8 Kanal mit 16 Bit Auflösung). Dafür entstand eine wirklich unausgegorene Software in VB6, die nichts weiter konnte, als den seriellen ADC per Parallelport auszulesen und CSV-Dateien zu schreiben. Die Auswertung erfolgte dann in Excel bzw. gnumeric unter Linux (was sich auch mit vielen Datensätzen als durchaus performant erwies). Der Zustand war für den Zweck der einfachen Messungen erträglich, wenn auch nicht wirklich optimal. In meinem zweiten Ausbildungsjahr "mussten" wir im Fach SAE (Programmieren) ein ''kleines'' Projekt in C# anfertigen. Dem ständigen Nachfragen nach einer vernünftigen Software nahm ich zum Anlass, einen etwas besseren Logger zu entwickeln. Für den angegebenen Rahmen - 12 Unterrichtsstunden + "Unterrichtsinteresse" - hab ich mir relativ hohe Zeile gesteckt: Auszug aus der Projektidee: * Grafische Benutzeroberfläche * Auswahl und Kalibrierung der zu messenden Kanäle der Hardware * Aufzeichnung von Messwerten * Grafische Auswertung der Messreihen * Speichern der Daten als CSV-Datei zur Weiterverarbeitung z. B. in Microsoft Excel Als kleines "Schmankerl" wurde die Hardware nicht per IEEE1284 oder RS232, sondern per USB angebunden, weiteres siehe [[Projektidee.pdf|Projektidee]] == Ende der Geschichte == Das Projekt wurde bis auf den letzten Punkt der Anforderungen vollständig programmiert (wenn auch nicht sonderlich schön) und es gab eine glatte 1 dafür. Um einen Eindruck in mein erstes C#-Projekt zu gewinnen, hier die [[Projektdoku.pdf|Projektdoku]]. ... blablabla ... == Anforderungen == * Unterstützung von Plugins ** Hardware (Eingabe) ''vorläufig fertig'' *** Momentan Testplugin mit ATTiny2313 + MAX1247 am USB ''fertig'' ** Visualisierung ''idee'' ** Algorithmen/Generelle ''idee'' ** Dateiformatunterstützung *** CSV ''noch nicht implementiert'' *** XML ''noch nicht implementiert'' *** SQLite ''idee'' *** Andere SQL-Datenbanken ''idee'' * Aufnahmen über längere Zeit * Datenvisualisierung ** Standard-Diagramm ''in Überarbeitung'' *** Notierfunktion ''idee' *** Hervorhebung von "besonderen" Werten ''idee'' ** Siehe Plugins ''to be continued...'' 135cc62719f715551b891975783e1bfec3214b16 319 310 2008-11-07T22:48:58Z Chris 2 Symbole und Infobox bei Anforderungen hinzugefügt wikitext text/x-wiki Diese Seite soll die Entstehung (und irgendwann mal die fertige Software) eines Datenloggers beschreiben. == Geschichte == Ursprung dieses Projekts ist irgendwann zwischen 2006 und 2007. [[Benutzer:Robert|Robert]] hatte die Idee bzw. den Bedarf nach einem Logger, um über längeren Zeitraum irgendetwas zu messen. Daraus entstand ein schönes Stück Hardware mit einem ADS8344 (8 Kanal mit 16 Bit Auflösung). Dafür entstand eine wirklich unausgegorene Software in VB6, die nichts weiter konnte, als den seriellen ADC per Parallelport auszulesen und CSV-Dateien zu schreiben. Die Auswertung erfolgte dann in Excel bzw. gnumeric unter Linux (was sich auch mit vielen Datensätzen als durchaus performant erwies). Der Zustand war für den Zweck der einfachen Messungen erträglich, wenn auch nicht wirklich optimal. In meinem zweiten Ausbildungsjahr "mussten" wir im Fach SAE (Programmieren) ein ''kleines'' Projekt in C# anfertigen. Dem ständigen Nachfragen nach einer vernünftigen Software nahm ich zum Anlass, einen etwas besseren Logger zu entwickeln. Für den angegebenen Rahmen - 12 Unterrichtsstunden + "Unterrichtsinteresse" - hab ich mir relativ hohe Zeile gesteckt: Auszug aus der Projektidee: * Grafische Benutzeroberfläche * Auswahl und Kalibrierung der zu messenden Kanäle der Hardware * Aufzeichnung von Messwerten * Grafische Auswertung der Messreihen * Speichern der Daten als CSV-Datei zur Weiterverarbeitung z. B. in Microsoft Excel Als kleines "Schmankerl" wurde die Hardware nicht per IEEE1284 oder RS232, sondern per USB angebunden, weiteres siehe [[Projektidee.pdf|Projektidee]] == Ende der Geschichte == Das Projekt wurde bis auf den letzten Punkt der Anforderungen vollständig programmiert (wenn auch nicht sonderlich schön) und es gab eine glatte 1 dafür. Um einen Eindruck in mein erstes C#-Projekt zu gewinnen, hier die [[Projektdoku.pdf|Projektdoku]]. == Anforderungen == {| class="toccolours" style="float: right; margin: 0 0 0.5em 1em; width: 250px;" ! style="font-size: larger; text-align: center;" | '''Legende''' |- |[[Bild:Projekt_idee16.png]] Idee [[Bild:Projekt_fasterledigt16.png]] Fast erledigt [[Bild:Projekt_erledigt16.png]] Erledigt [[Bild:Projekt_ueberarbeiten16.png]] Wird überarbeitet [[Bild:Projekt_verworfen16.png]] Verworfen [[Bild:Projekt_fehler16.png]] (Noch) fehlerhaft [[Bild:Projekt_entwickeln16.png]] Wird momentan entwickelt |} * Unterstützung von Plugins ** Hardware (Eingabe) [[Bild:Projekt_fasterledigt16.png]] *** Momentan Testplugin mit ATTiny2313 + MAX1247 am USB [[Bild:Projekt_erledigt16.png]] ** Visualisierung [[Bild:Projekt_idee16.png]] ** Algorithmen/Generelle [[Bild:Projekt_idee16.png]] ** Dateiformate *** CSV *** XML *** SQLite [[Bild:Projekt_idee16.png]] *** Andere SQL-Datenbanken [[Bild:Projekt_idee16.png]] * Datenvisualisierung ** Standard-Diagramm [[Bild:Projekt_ueberarbeiten16.png]] [[Bild:Projekt_entwickeln16.png]] *** Notizen [[Bild:Projekt_idee16.png]] *** Hervorhebung von "besonderen" Werten [[Bild:Projekt_idee16.png]] *** Achsen **** Zeitachse [[Bild:Projekt_erledigt16.png]] **** Wertachse [[Bild:Projekt_fasterledigt16.png]] [[Bild:Projekt_ueberarbeiten16.png]] ** Siehe Plugins ''to be continued...'' d6075c860b2e8fdaa1b350ba1a1b37cb8aa8b7aa 322 319 2009-01-19T22:17:33Z Chris 2 Abschnitt Bargraphs hinzugefügt wikitext text/x-wiki Diese Seite soll die Entstehung (und irgendwann mal die fertige Software) eines Datenloggers beschreiben. == Geschichte == Ursprung dieses Projekts ist irgendwann zwischen 2006 und 2007. [[Benutzer:Robert|Robert]] hatte die Idee bzw. den Bedarf nach einem Logger, um über längeren Zeitraum irgendetwas zu messen. Daraus entstand ein schönes Stück Hardware mit einem ADS8344 (8 Kanal mit 16 Bit Auflösung). Dafür entstand eine wirklich unausgegorene Software in VB6, die nichts weiter konnte, als den seriellen ADC per Parallelport auszulesen und CSV-Dateien zu schreiben. Die Auswertung erfolgte dann in Excel bzw. gnumeric unter Linux (was sich auch mit vielen Datensätzen als durchaus performant erwies). Der Zustand war für den Zweck der einfachen Messungen erträglich, wenn auch nicht wirklich optimal. In meinem zweiten Ausbildungsjahr "mussten" wir im Fach SAE (Programmieren) ein ''kleines'' Projekt in C# anfertigen. Dem ständigen Nachfragen nach einer vernünftigen Software nahm ich zum Anlass, einen etwas besseren Logger zu entwickeln. Für den angegebenen Rahmen - 12 Unterrichtsstunden + "Unterrichtsinteresse" - hab ich mir relativ hohe Zeile gesteckt: Auszug aus der Projektidee: * Grafische Benutzeroberfläche * Auswahl und Kalibrierung der zu messenden Kanäle der Hardware * Aufzeichnung von Messwerten * Grafische Auswertung der Messreihen * Speichern der Daten als CSV-Datei zur Weiterverarbeitung z. B. in Microsoft Excel Als kleines "Schmankerl" wurde die Hardware nicht per IEEE1284 (mein heiß geliebter Parallelport, der aber immer mehr ausstirbt) oder RS232, sondern per USB angebunden, weiteres siehe [[Projektidee.pdf|Projektidee]] == Ende der Geschichte == Das Projekt wurde bis auf den letzten Punkt der Anforderungen vollständig programmiert (wenn auch nicht sonderlich schön) und es gab eine glatte 1 dafür. Um einen Eindruck in mein erstes C#-Projekt zu gewinnen, hier die [[Projektdoku.pdf|Projektdoku]]. == Anforderungen == {| class="toccolours" style="float: right; margin: 0 0 0.5em 1em; width: 250px;" ! style="font-size: larger; text-align: center;" | '''Legende''' |- |[[Bild:Projekt_idee16.png]] Idee [[Bild:Projekt_fasterledigt16.png]] Fast erledigt [[Bild:Projekt_erledigt16.png]] Erledigt [[Bild:Projekt_ueberarbeiten16.png]] Wird überarbeitet [[Bild:Projekt_verworfen16.png]] Verworfen [[Bild:Projekt_fehler16.png]] (Noch) fehlerhaft [[Bild:Projekt_entwickeln16.png]] Wird momentan entwickelt |} * Unterstützung von Plugins ** Hardware (Eingabe) [[Bild:Projekt_fasterledigt16.png]] *** Momentan Testplugin mit ATTiny2313 + MAX1247 am USB [[Bild:Projekt_erledigt16.png]] ** Visualisierung [[Bild:Projekt_idee16.png]] ** Algorithmen/Generelle [[Bild:Projekt_idee16.png]] ** Dateiformate *** CSV *** XML *** SQLite [[Bild:Projekt_idee16.png]] *** Andere SQL-Datenbanken [[Bild:Projekt_idee16.png]] * Datenvisualisierung ** Standard-Diagramm [[Bild:Projekt_ueberarbeiten16.png]] [[Bild:Projekt_entwickeln16.png]] *** Notizen [[Bild:Projekt_idee16.png]] *** Hervorhebung von "besonderen" Werten [[Bild:Projekt_idee16.png]] *** Achsen **** Zeitachse [[Bild:Projekt_erledigt16.png]] (+ Scrollbar) **** Wertachse [[Bild:Projekt_erledigt16.png]] ** Siehe Plugins == Bargraphs == Damit sich das Warten auch lohnt, hier zwei kleine Einblicke in die Bargraphs: [[Bild:Logger_HBar.png]] [[Bild:Logger_VBar.png]] Im horizontalen Bargraph befinden sich drei Vermerke, die wie folgt hinzugefügt wurden: <pre> horizontalBar1.Annotations.Add(new Bargraph.Annotation(0, 2, Color.Gold, "")); horizontalBar1.Annotations.Add(new Bargraph.Annotation(400, 1.5F, Color.Red, "")); horizontalBar1.Annotations.Add(new Bargraph.Annotation(600, 4, Color.Blue, "")); </pre> Eine kleine Demo des horizontalen Bargraphs gibt's im [http://hobbyelektronik.org/b/?p=66 Blog] ''to be continued...'' [[Kategorie:Software]] bf74f5994f7fe32525742010c3b7f700a7b8db02 324 322 2009-01-20T22:01:17Z Chris 2 Demo für den vertikalen Bargraph hinzugefügt wikitext text/x-wiki Diese Seite soll die Entstehung (und irgendwann mal die fertige Software) eines Datenloggers beschreiben. == Geschichte == Ursprung dieses Projekts ist irgendwann zwischen 2006 und 2007. [[Benutzer:Robert|Robert]] hatte die Idee bzw. den Bedarf nach einem Logger, um über längeren Zeitraum irgendetwas zu messen. Daraus entstand ein schönes Stück Hardware mit einem ADS8344 (8 Kanal mit 16 Bit Auflösung). Dafür entstand eine wirklich unausgegorene Software in VB6, die nichts weiter konnte, als den seriellen ADC per Parallelport auszulesen und CSV-Dateien zu schreiben. Die Auswertung erfolgte dann in Excel bzw. gnumeric unter Linux (was sich auch mit vielen Datensätzen als durchaus performant erwies). Der Zustand war für den Zweck der einfachen Messungen erträglich, wenn auch nicht wirklich optimal. In meinem zweiten Ausbildungsjahr "mussten" wir im Fach SAE (Programmieren) ein ''kleines'' Projekt in C# anfertigen. Dem ständigen Nachfragen nach einer vernünftigen Software nahm ich zum Anlass, einen etwas besseren Logger zu entwickeln. Für den angegebenen Rahmen - 12 Unterrichtsstunden + "Unterrichtsinteresse" - hab ich mir relativ hohe Zeile gesteckt: Auszug aus der Projektidee: * Grafische Benutzeroberfläche * Auswahl und Kalibrierung der zu messenden Kanäle der Hardware * Aufzeichnung von Messwerten * Grafische Auswertung der Messreihen * Speichern der Daten als CSV-Datei zur Weiterverarbeitung z. B. in Microsoft Excel Als kleines "Schmankerl" wurde die Hardware nicht per IEEE1284 (mein heiß geliebter Parallelport, der aber immer mehr ausstirbt) oder RS232, sondern per USB angebunden, weiteres siehe [[Projektidee.pdf|Projektidee]] == Ende der Geschichte == Das Projekt wurde bis auf den letzten Punkt der Anforderungen vollständig programmiert (wenn auch nicht sonderlich schön) und es gab eine glatte 1 dafür. Um einen Eindruck in mein erstes C#-Projekt zu gewinnen, hier die [[Projektdoku.pdf|Projektdoku]]. == Anforderungen == {| class="toccolours" style="float: right; margin: 0 0 0.5em 1em; width: 250px;" ! style="font-size: larger; text-align: center;" | '''Legende''' |- |[[Bild:Projekt_idee16.png]] Idee [[Bild:Projekt_fasterledigt16.png]] Fast erledigt [[Bild:Projekt_erledigt16.png]] Erledigt [[Bild:Projekt_ueberarbeiten16.png]] Wird überarbeitet [[Bild:Projekt_verworfen16.png]] Verworfen [[Bild:Projekt_fehler16.png]] (Noch) fehlerhaft [[Bild:Projekt_entwickeln16.png]] Wird momentan entwickelt |} * Unterstützung von Plugins ** Hardware (Eingabe) [[Bild:Projekt_fasterledigt16.png]] *** Momentan Testplugin mit ATTiny2313 + MAX1247 am USB [[Bild:Projekt_erledigt16.png]] ** Visualisierung [[Bild:Projekt_idee16.png]] ** Algorithmen/Generelle [[Bild:Projekt_idee16.png]] ** Dateiformate *** CSV *** XML *** SQLite [[Bild:Projekt_idee16.png]] *** Andere SQL-Datenbanken [[Bild:Projekt_idee16.png]] * Datenvisualisierung ** Standard-Diagramm [[Bild:Projekt_ueberarbeiten16.png]] [[Bild:Projekt_entwickeln16.png]] *** Notizen [[Bild:Projekt_idee16.png]] *** Hervorhebung von "besonderen" Werten [[Bild:Projekt_idee16.png]] *** Achsen **** Zeitachse [[Bild:Projekt_erledigt16.png]] (+ Scrollbar) **** Wertachse [[Bild:Projekt_erledigt16.png]] ** Siehe Plugins == Bargraphs == Damit sich das Warten auch lohnt, hier zwei kleine Einblicke in die Bargraphs: [[Bild:Logger_HBar.png]] [[Bild:Logger_VBar.png]] Im horizontalen Bargraph befinden sich drei Vermerke, die wie folgt hinzugefügt wurden: <pre> horizontalBar1.Annotations.Add(new Bargraph.Annotation(0, 2, Color.Gold, "")); horizontalBar1.Annotations.Add(new Bargraph.Annotation(400, 1.5F, Color.Red, "")); horizontalBar1.Annotations.Add(new Bargraph.Annotation(600, 4, Color.Blue, "")); </pre> Eine kleine Demo des horizontalen Bargraphs gibt's im [http://hobbyelektronik.org/b/?p=66 Blog] Für den vertikalen Bargraph gibt es nun auch eine Demo: [http://hobbyelektronik.org/b/?p=75 >klick<] ''to be continued...'' [[Kategorie:Software]] 8eb6a3694dc4306e07d574b43b8b91091c9454b8 Datei:Projekt entwickeln16.png 6 77 311 2008-11-07T22:13:45Z Chris 2 Icon aus CrystalClear Punkte, die entwickelt werden wikitext text/x-wiki Icon aus CrystalClear Punkte, die entwickelt werden 5833130d231fbdd51a0769bf30b7866034ce53eb Datei:Projekt fehler16.png 6 78 312 2008-11-07T22:14:14Z Chris 2 Icon aus CrystalClear Punkte, die Fehler haben wikitext text/x-wiki Icon aus CrystalClear Punkte, die Fehler haben 6d7310ffedd3d2aff5ce657b6512837b81b2a4fc Datei:Projekt idee16.png 6 79 313 2008-11-07T22:14:27Z Chris 2 Icon aus CrystalClear Punkte, die Ideen sind wikitext text/x-wiki Icon aus CrystalClear Punkte, die Ideen sind bb9ca4aeddbd11f3b9984d79267fd12089f68d09 Datei:Projekt meilenstein32.png 6 80 314 2008-11-07T22:14:41Z Chris 2 Icon aus CrystalClear Meilensteine wikitext text/x-wiki Icon aus CrystalClear Meilensteine f20e669350d0aed3729b301dd3f1f1480ea2236c Datei:Projekt verworfen16.png 6 81 315 2008-11-07T22:14:55Z Chris 2 Icon aus CrystalClear Punkte, die verworfen wurden wikitext text/x-wiki Icon aus CrystalClear Punkte, die verworfen wurden 0ede4c7a23ef5c4fcbce8a78dbceea779b45f051 Datei:Projekt erledigt16.png 6 82 316 2008-11-07T22:18:16Z Chris 2 Icon aus CrystalClear Punkte, die erledigt sind wikitext text/x-wiki Icon aus CrystalClear Punkte, die erledigt sind 8e13adc7fcad74e066f3d822cf49b49058eb308c Datei:Projekt fasterledigt16.png 6 83 317 2008-11-07T22:18:27Z Chris 2 Icon aus CrystalClear Punkte, die fast erledigt sind wikitext text/x-wiki Icon aus CrystalClear Punkte, die fast erledigt sind 23c23c83a3a1b5519ed22e1851b5c4c61552bac5 Datei:Projekt ueberarbeiten16.png 6 84 318 2008-11-07T22:23:27Z Chris 2 Icon von Mozilla Firefox Punkte, die fast erledigt sind wikitext text/x-wiki Icon von Mozilla Firefox Punkte, die fast erledigt sind 0bf09956d8ab88d68f344793b22bd4be0a78eac9 Datei:Logger HBar.png 6 85 320 2009-01-19T21:57:32Z Chris 2 Horizontaler Bargraph für den Logger wikitext text/x-wiki Horizontaler Bargraph für den Logger 7954227b7e19d241a2e49fda34fd1d418556c470 Datei:Logger VBar.png 6 86 321 2009-01-19T21:58:11Z Chris 2 Vertikaler Bargraph für den Logger wikitext text/x-wiki Vertikaler Bargraph für den Logger b7a2d8fc9a01e81463e3d98efa00a4c18eed6568 Datei:Touchlight Ladekurve.png 6 89 331 2009-06-28T13:59:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Touchlight Helligkeit.png 6 90 333 2009-07-02T19:58:57Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 334 333 2009-07-02T20:08:05Z Chris 2 hat eine neue Version von „[[Datei:Touchlight Helligkeit.png]]“ hochgeladen wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Touchlight Schem.png 6 91 335 2009-07-03T22:20:24Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Touchlight 0 92 336 2009-07-03T22:21:51Z Chris 2 Seite angelegt wikitext text/x-wiki Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. == Leuchtmittel == Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "untrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos sortieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen. Da dieser über zwei Hardware-PWMs verfügt, sollen diese auch genutzt werden. Deswegen werden die LED-Leisten in zwei Stränge unterteilt - die Anzahl wird einzig durch das Netzteil beschränkt - einem austemusterten SonyEricsson-Ladegerät. Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. == Bedienung == Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. == Theorie == [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> U(t) = U0*(1-e^(-t/(R*C)) Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. == Die Software == Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <pre> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~(1<<pin); //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & (1<<pin)) && --sampletime); //Zeit messen KEYDDR |= 1<<pin; //Pin als Ausgang -> entladen return sampletime; } </pre> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <pre> ... i = 0; n = 6; while(--n) { i += getcap(PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </pre> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <pre> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </pre> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. (Download folgt) b38c7f3e97d5f37fa7272ebcee8ce69229f59799 337 336 2009-07-03T22:23:09Z Chris 2 ...und natürlich hab ich die Kategorie vergessen wikitext text/x-wiki Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. == Leuchtmittel == Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "untrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos sortieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen. Da dieser über zwei Hardware-PWMs verfügt, sollen diese auch genutzt werden. Deswegen werden die LED-Leisten in zwei Stränge unterteilt - die Anzahl wird einzig durch das Netzteil beschränkt - einem austemusterten SonyEricsson-Ladegerät. Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. == Bedienung == Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. [Kategorie:AVR] Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. == Theorie == [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> U(t) = U0*(1-e^(-t/(R*C)) Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. == Die Software == Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <pre> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~(1<<pin); //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & (1<<pin)) && --sampletime); //Zeit messen KEYDDR |= 1<<pin; //Pin als Ausgang -> entladen return sampletime; } </pre> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <pre> ... i = 0; n = 6; while(--n) { i += getcap(PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </pre> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <pre> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </pre> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. (Download folgt) [[Category:AVR]] 5531841a1019717018a5c0527bec6ace4a1173dc 340 337 2009-07-05T21:24:02Z Chris 2 Download hinzugefügt wikitext text/x-wiki Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. == Leuchtmittel == Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "untrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos sortieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen. Da dieser über zwei Hardware-PWMs verfügt, sollen diese auch genutzt werden. Deswegen werden die LED-Leisten in zwei Stränge unterteilt - die Anzahl wird einzig durch das Netzteil beschränkt - einem austemusterten SonyEricsson-Ladegerät. Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. == Bedienung == Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. [Kategorie:AVR] Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. == Theorie == [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> U(t) = U0*(1-e^(-t/(R*C)) Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. == Die Software == Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <pre> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~pin; //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & pin) && --sampletime); //Zeit messen KEYDDR |= pin; //Pin als Ausgang -> entladen return sampletime; } </pre> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <pre> ... i = 0; n = 6; while(--n) { i += getcap(1<<PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </pre> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <pre> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </pre> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. == Download == [[Datei:Touch_1.0.zip]] Enthält sowohl den simplen Touchsensor CPU-Takt muss jeweils 9,6MHz sein, der Rest nach eigenem Ermessen. Stromlaufpläne ist bei beiden Sourcen gleich, bei TouchSense ist zusätzlich der (nicht-invertierte) UART auf PBO. Dort werden die Messwerte der beiden Sensoren Tab-getrennt ausgegeben. die Konstante MINDELAY für den UART-Pause in suart.c muss wahrscheinlich angepasst werden. [[Category:AVR]] 55e970c33ecdca705c7c42bb92e1ae318021517a Datei:Touch 1.0.zip 6 93 339 2009-07-05T21:17:06Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 SNES-Joypad 0 35 342 53 2009-07-05T21:34:38Z Chris 2 AVR-USB ist jetzt V-USB ;) wikitext text/x-wiki Als Kind hatte ich mir mal (ja, aus eigener Tasche) einen Super Nintendo gekauft. Nachdem er die Jahre leider nicht überlebt hat und ich doch ab und an mal ein bisschen Verlangen nach SNES habe, griff ich auf Emulatoren für den PC zurück. So gut die Programme auch sind - man hat ein Problem: man muss auf der Tastatur spielen. Das mag bei manchen Spielen noch gehen, wenn man jedoch in brenzliche Situationen kommt, braucht man dann doch die etwas trainierteren Daumen. Irgendwann kam ich auf die Idee, einfach das Gamepad an den PC anzuschließen. Mit einem Nachbau eines SNES-Gamepads, das ich mal geschenkt bekommen habe, funktionierte das ziemlich gut. Im Pad selbst waren zwei CD4021 (Schieberegister) verbaut. Die Funktionsweise des Gamepads ist somit genauso simpel wie... simpel. Wenn die CPU in der Konsole den Controller auslesen will, werden die Daten per Latch in das Register geladen, von wo es dann seriell ausgelesen werden kann. [[Bild:SNES-stecker.jpg|thumb|Anschlussbelegung am Stecker]] Die Beschaltung im Controller ist folgendermaßen: {| ! Pin|| Farbe || Funktion |- | 1 || braun || GND |- | 2 || rot || Data |- | 3 || orange || Latch |- | 4 || gelb || Clock |- | 5 || weiß || Vcc |} Bei meiner ersten Entwicklung war das Gamepad am Parallel-Port angeschlossen und wurde von einem kleinen VB-Programm ausgelesen. Die Tastenanschläge wurden dann per DLL als Tastatur-Eingaben simuliert. Das ganze hatte nur ein paar Nachteile: * Die Software war nicht besonders schön * Der Parallelport wurde (mal wieder) zweckentfremdet * Man muss hinter den PC kriechen, wenn man wieder etwas drucken will * Das Ganze ist einfach nicht rund (vorangegangene Punkte) * Mein Notebook hat weder eine parallele noch serielle Schnittstelle Irgendwann entdeckte ich [http://www.obdev.at/products/vusb/index-de.html V-USB], eine Software-Implementierung von USB in AVRs. Als Projekt war [http://www.raphnet.net/electronique/snes_nes_usb/index_en.php SNES/NES gamepad (and mouse) to USB adapter] verlinkt. Die Schaltung habe ich mir dann relativ zügig aufgebaut, um zu testen, ob da wirklich das dahintersteckt, was ich mir erwartet hatte. Tatsächlich meldete Windows 2s nach dem Einstecken der Konstruktion eine neue Hardware. Nur die Tatsache, dass an einem 28-Pin-Mikrocontroller nur ca. 10 Pins und auf den 8KB Speicher nur 3 belegt waren und das Ganze nicht richtig im Gamecontroller untergebracht werden konnte, störte mich ein wenig. Vor kurzem las ich dann folgendes auf obdev.at: <pre> New: Internal RC Oscillator Supported AVR-USB supports the internal RC oscillator of all AVRs with internal high frequency PLL, such as the ATTiny45 or ATTiny26. No external crystal is needed on these devices! See the EasyLogger example for details. </pre> Das war das, worauf ich gewartet hatte: Der ATTiny45 hat 8 Beine, wofür 2 für USB und weitere 3 für die Standardbeschaltung verwendet werden. Somit bleiben genau die benötigten drei Anschlüsse für das Gamepad frei. Die Beispielanwendung für die Impementierung ([http://www.obdev.at/products/avrusb/easylogger.html EasyLogger]) zielt schon sehr gut in die Richtung, in die ich gehen will. Der Großteil des Quelltextes konnte beibehalten werden, Teile kamen von Raph und wurden ziemlich stark umgebaut. Nachdem ich einige Wochen zuvor kläglich daran gescheitert bin, die Software von oben auf den ATTiny2313 zu portieren, nahm ich mir zum Ziel, den Quelltext so klein wie möglich zu gestalten. Nach etlichen Optimierversuchen und Brennvorgängen war es dann geschafft: Das kompilierte Programm ist exakt 2000 Byte groß. Leider hat der Device-Name etwas darunter gelitten - es ist allerdings noch deutlich erkennbar, worum es sich handelt. Ein weiteres Ziel war, die Elektronik im Controller unterzubringen, sodass nur noch ein USB-Kabel ohne weitere Elektronik am PC angeschlossen wird. Netterweise ist im Gamepad ziemlich viel Platz vorhanden, welcher erlaubt, selbst einen DIP-IC aufgelötet auf einer Platine zu fassen. Also flugs die Schaltung vom Steckbrett auf die Platine bringen. Nach dem ersten Test am PC war ich etwas irritiert: kein fröhliches "Plüm-Plim" vom PC, stattdessen kam nach einigen Wartesekunden ein "Plopp" aus den Lautsprechern: "Hardware wurde nicht erkannt". IC ausgelötet und wieder aufs Steckbrett: "Plüm-Plim" (Hardware erkannt). Auch nach langem Suchen war kein Fehler in der Schaltung zu finden. Also zurück an den Anfang: [[PLL im ATTiny45 kalibrieren]]. [[Bild:SNES-einbau.jpg|thumb|Einbau des V-USB-Controllers im SNES-Gamepad]] Nach ein paar Versuchen klappte es auch und ich konnte das Gamepad wieder schließen. Wenn mich jetzt die Lust packt heißt es nur noch Controller vorne am PC an einem freien USB-Port anschließen und losspielen. Da der Aufbau auf Lochraster zwar "ganz nett" ist, aber noch nicht der Weisheit letzter Schluss ist, habe eine kleine Schaltung + Platine in SMD in EAGLE erstellt: [[Bild:SNES-brd.png|thumb|none]] Die Schaltung ist zwar nicht gerade ideal zum Brennen des AVRs, aber evtl. könnte es klappen, wenn man die Anschlüsse für USB (oben) und für den SNES-Controllers (unten) ausnutzt. Leider kommt man nicht 'drum, einen Draht direkt an RESET zu löten. Platz für einen Testpin ist leider nicht mehr vorhanden. Die Anschlussbelegungen sind jeweils nach den Standards. Auf der SNES-Seite wie oben angegeben, auf USB-Seite so wie im USB-Standard angegeben (Näheres ist dem Stromlaufplan in der ZIP-Datei zu entnehmen). == Download == Die Firmware ist unkompiliert, da der OSCCAL-Wert nicht automatisch ermittelt wird. Weiterhin wurde kein Kompilat beigelegt, da das verwendete VID/PID-Paar (siehe usbconfig.h) nicht mir gehört und von jedem, der die Hardware einsetzt durch sein Paar ersetzt werden muss. (Wenn man die Schaltung für sich daheim privat betreibt, sollte es jedoch keine Probleme geben) == Nachtrag (07/2009) == Das Kalibrieren des PLLs kann seit einiger Zeit wegfallen - es gibt nun die Möglichkeit, die PLL anhand der USB-Framelänge beim Anschließen der USB-Devices zu kalibrieren. Habe es selber schon erfolgreich getestet. Näheres dazu: [http://vusb.wikidot.com/examples#toc4 Clocking the AVR from the RC oscillator with auto-calibration]. Achtung: DIE FIRMWARE HIER ENTHÄLT DIESES FEATURE NOCH NICHT! [[Bild:SNES-USB.zip]] [[Category:PC]] [[Category:AVR]] [[Category:USB]] 2c9174185b2818ecd1fcc648c60a19305e9c39f3 343 342 2009-11-18T08:59:33Z Chris 2 l vergessen, danke an Stefan ;) wikitext text/x-wiki Als Kind hatte ich mir mal (ja, aus eigener Tasche) einen Super Nintendo gekauft. Nachdem er die Jahre leider nicht überlebt hat und ich doch ab und an mal ein bisschen Verlangen nach SNES habe, griff ich auf Emulatoren für den PC zurück. So gut die Programme auch sind - man hat ein Problem: man muss auf der Tastatur spielen. Das mag bei manchen Spielen noch gehen, wenn man jedoch in brenzliche Situationen kommt, braucht man dann doch die etwas trainierteren Daumen. Irgendwann kam ich auf die Idee, einfach das Gamepad an den PC anzuschließen. Mit einem Nachbau eines SNES-Gamepads, das ich mal geschenkt bekommen habe, funktionierte das ziemlich gut. Im Pad selbst waren zwei CD4021 (Schieberegister) verbaut. Die Funktionsweise des Gamepads ist somit genauso simpel wie... simpel. Wenn die CPU in der Konsole den Controller auslesen will, werden die Daten per Latch in das Register geladen, von wo es dann seriell ausgelesen werden kann. [[Bild:SNES-stecker.jpg|thumb|Anschlussbelegung am Stecker]] Die Beschaltung im Controller ist folgendermaßen: {| ! Pin|| Farbe || Funktion |- | 1 || braun || GND |- | 2 || rot || Data |- | 3 || orange || Latch |- | 4 || gelb || Clock |- | 5 || weiß || Vcc |} Bei meiner ersten Entwicklung war das Gamepad am Parallel-Port angeschlossen und wurde von einem kleinen VB-Programm ausgelesen. Die Tastenanschläge wurden dann per DLL als Tastatur-Eingaben simuliert. Das ganze hatte nur ein paar Nachteile: * Die Software war nicht besonders schön * Der Parallelport wurde (mal wieder) zweckentfremdet * Man muss hinter den PC kriechen, wenn man wieder etwas drucken will * Das Ganze ist einfach nicht rund (vorangegangene Punkte) * Mein Notebook hat weder eine parallele noch serielle Schnittstelle Irgendwann entdeckte ich [http://www.obdev.at/products/vusb/index-de.html V-USB], eine Software-Implementierung von USB in AVRs. Als Projekt war [http://www.raphnet.net/electronique/snes_nes_usb/index_en.php SNES/NES gamepad (and mouse) to USB adapter] verlinkt. Die Schaltung habe ich mir dann relativ zügig aufgebaut, um zu testen, ob da wirklich das dahintersteckt, was ich mir erwartet hatte. Tatsächlich meldete Windows 2s nach dem Einstecken der Konstruktion eine neue Hardware. Nur die Tatsache, dass an einem 28-Pin-Mikrocontroller nur ca. 10 Pins und auf den 8KB Speicher nur 3 belegt waren und das Ganze nicht richtig im Gamecontroller untergebracht werden konnte, störte mich ein wenig. Vor kurzem las ich dann folgendes auf obdev.at: <pre> New: Internal RC Oscillator Supported AVR-USB supports the internal RC oscillator of all AVRs with internal high frequency PLL, such as the ATTiny45 or ATTiny26. No external crystal is needed on these devices! See the EasyLogger example for details. </pre> Das war das, worauf ich gewartet hatte: Der ATTiny45 hat 8 Beine, wofür 2 für USB und weitere 3 für die Standardbeschaltung verwendet werden. Somit bleiben genau die benötigten drei Anschlüsse für das Gamepad frei. Die Beispielanwendung für die Implementierung ([http://www.obdev.at/products/avrusb/easylogger.html EasyLogger]) zielt schon sehr gut in die Richtung, in die ich gehen will. Der Großteil des Quelltextes konnte beibehalten werden, Teile kamen von Raph und wurden ziemlich stark umgebaut. Nachdem ich einige Wochen zuvor kläglich daran gescheitert bin, die Software von oben auf den ATTiny2313 zu portieren, nahm ich mir zum Ziel, den Quelltext so klein wie möglich zu gestalten. Nach etlichen Optimierversuchen und Brennvorgängen war es dann geschafft: Das kompilierte Programm ist exakt 2000 Byte groß. Leider hat der Device-Name etwas darunter gelitten - es ist allerdings noch deutlich erkennbar, worum es sich handelt. Ein weiteres Ziel war, die Elektronik im Controller unterzubringen, sodass nur noch ein USB-Kabel ohne weitere Elektronik am PC angeschlossen wird. Netterweise ist im Gamepad ziemlich viel Platz vorhanden, welcher erlaubt, selbst einen DIP-IC aufgelötet auf einer Platine zu fassen. Also flugs die Schaltung vom Steckbrett auf die Platine bringen. Nach dem ersten Test am PC war ich etwas irritiert: kein fröhliches "Plüm-Plim" vom PC, stattdessen kam nach einigen Wartesekunden ein "Plopp" aus den Lautsprechern: "Hardware wurde nicht erkannt". IC ausgelötet und wieder aufs Steckbrett: "Plüm-Plim" (Hardware erkannt). Auch nach langem Suchen war kein Fehler in der Schaltung zu finden. Also zurück an den Anfang: [[PLL im ATTiny45 kalibrieren]]. [[Bild:SNES-einbau.jpg|thumb|Einbau des V-USB-Controllers im SNES-Gamepad]] Nach ein paar Versuchen klappte es auch und ich konnte das Gamepad wieder schließen. Wenn mich jetzt die Lust packt heißt es nur noch Controller vorne am PC an einem freien USB-Port anschließen und losspielen. Da der Aufbau auf Lochraster zwar "ganz nett" ist, aber noch nicht der Weisheit letzter Schluss ist, habe eine kleine Schaltung + Platine in SMD in EAGLE erstellt: [[Bild:SNES-brd.png|thumb|none]] Die Schaltung ist zwar nicht gerade ideal zum Brennen des AVRs, aber evtl. könnte es klappen, wenn man die Anschlüsse für USB (oben) und für den SNES-Controllers (unten) ausnutzt. Leider kommt man nicht 'drum, einen Draht direkt an RESET zu löten. Platz für einen Testpin ist leider nicht mehr vorhanden. Die Anschlussbelegungen sind jeweils nach den Standards. Auf der SNES-Seite wie oben angegeben, auf USB-Seite so wie im USB-Standard angegeben (Näheres ist dem Stromlaufplan in der ZIP-Datei zu entnehmen). == Download == Die Firmware ist unkompiliert, da der OSCCAL-Wert nicht automatisch ermittelt wird. Weiterhin wurde kein Kompilat beigelegt, da das verwendete VID/PID-Paar (siehe usbconfig.h) nicht mir gehört und von jedem, der die Hardware einsetzt durch sein Paar ersetzt werden muss. (Wenn man die Schaltung für sich daheim privat betreibt, sollte es jedoch keine Probleme geben) == Nachtrag (07/2009) == Das Kalibrieren des PLLs kann seit einiger Zeit wegfallen - es gibt nun die Möglichkeit, die PLL anhand der USB-Framelänge beim Anschließen der USB-Devices zu kalibrieren. Habe es selber schon erfolgreich getestet. Näheres dazu: [http://vusb.wikidot.com/examples#toc4 Clocking the AVR from the RC oscillator with auto-calibration]. Achtung: DIE FIRMWARE HIER ENTHÄLT DIESES FEATURE NOCH NICHT! [[Bild:SNES-USB.zip]] [[Category:PC]] [[Category:AVR]] [[Category:USB]] 857f32859cd6fd4eba35f04a9fba2204f795a55a Datei:Usblotio povray.jpg 6 94 344 2009-12-21T21:35:59Z Chris 2 Mit [http://www.povray.org/ POV-Ray] gerendeters Layout der USBLotIO-Platinen wikitext text/x-wiki Mit [http://www.povray.org/ POV-Ray] gerendeters Layout der USBLotIO-Platinen e0e45e5f431138827ebd7d985d5d7a9270fa1bfd USBLotIO 0 95 345 2009-12-21T21:48:50Z Chris 2 im Entstehen... wikitext text/x-wiki Die parallele Schnittstelle am PC ist tot. Nachdem sie schon vor einigen Jahren bei Notebooks verschwunden ist, findet man sie heute auch kaum noch bei Desktop-PCs. Selbst bei teureren Mainboards sind oft nur noch Pinheader vorhanden. Ein Slotblech dafür wird generell nicht geliefert. Die ganzen Drucker sind jetzt schneller und mit dünneren Leitungen per USB angebunden. Soweit, so gut. Nur wird die Luft für Bastler langsam dünner, wenn man keine größeren Ambitionen zu RS232 hat (deren Anschlüsse am PC auch langsam aussterben). Aus diesem Grund hatte ich die Idee, eine kleine Schaltung zu bauen, die zwar keinen Ersatz aber eine Alternative zum guten alten Parport darstellt. == Anforderungen == * Anbindung, die auch noch in ein paar Jahren funktioniert * Einfacher Aufbau * Einfach vom PC ansprechbar * Erweiterbar == Hardware == [[Bild:Usblotio_povray.jpg|thumb|Mit [http://www.povray.org/ POV-Ray] gerendertes Layout der Platinen]] Die Anbindung an den PC findet per USB statt. Hier soll (wieder einmal) [http://www.obdev.at/products/vusb/index-de.html V-USB] zum Einsatz kommen. Davon gibt es zwar schon ein Referenzdesign ([http://www.obdev.at/products/vusb/powerswitch.html PowerSwitch]), dieses hat meiner Meinung ein paar Schwachstellen: * keine Erweiterbarkeit * Treiber erforderlich (laufen die vorhandenen überhaupt unter Win7?) * relativ großer Aufbau Diesen Schwächen möchte ich mit einem ATTiny45 entgegenwirken. Dieser ist schön klein und braucht dank PLL (und automatischer Taktkalibrierung per USB) keinen externen Quarz. Damit man keine Treiber braucht, soll er sich dem Computer gegenüber als HID (Human Interface Device) ausgeben. Bleibt nur noch eines: Mit der Anbindung am PC bleiben nur noch 4 Pins am Tiny über - einer davon ist der Reset-Eingang - wie soll man da großartig Ausgänge schalten können? Ganz zu schweigen von der angestrebten Erweiterbarkeit... Die Lösung hierfür ist einfach: der Mikrocontroller steuert Schieberegister an, die beliebig kaskadiert werden können. So kann man quasi beliebig viele Ausgänge an den AVR dengeln. Als Ausgabeschieberegister dienen 74xx595, welche einen Latch haben und die Datenleitungen in einem Rutsch aktualisiert werden können. Um Signale auch lesen zu können, kommen 74xx165 zum Einsatz. Zwar haben diese auch einen Latch, allerdings ist dieser (anders als beim 595) low-aktiv. Damit wird's mit 4 I/Os am AVR eng. Gut, die Strobe-Leitungen muss man trennen, Clock kann gemeinsam laufen, nur sind jetzt schon alle Pins belegt. Es ist zwar möglich, die Daten ins Register zu laden, aber was bringen die Daten, wenn man sie nicht lesen kann? Mit einem kleinen Trick kann man das aber bewältigen: Die Datenleitungen beider Richtungen auf einen I/O. Zum Schutz des Ausganges des Registers gibt es aber einen Reihenwiderstand. Zwischen dem Lesen und Schreiben muss die Datenleitung einfach nur noch als Eingang bzw. Ausgang geschalten werden. Aber Vorsicht: dadurch, dass der Reset-Pin auch verwendet wird, kann der Mikrocontroller nur mit HVSP programmiert werden! (oder man lässt eine "Richtung" weg). == Software == === AVR === Wie bereits erwähnt läuft auf dem AVR objective developments V-USB als HID. Grundlage für meine Implementierung war das "Datastore"-Beispiel, das zusätzlich um die automatische Kalibrierung der CPU-Frequenz erweitert wurde. Da die USB-Schnittstelle zwangsläufig auf einem Interrupt-Pin hängt, der gleichzeitig auch für SPI verantwortlich ist, müssen die Schieberegister mit einem wesentlich langsameren Soft-SPI angesprochen werden. Der USB-Client reagiert bei dem Beginn einer Übertragung mit einem Aufruf der Methode usbFunctionSetup. In ihr wird dann entschieden, ob es sich um einen Schreib- oder Lesevorgang handelt. Hier wird zum einen die Speicheradresse auf 0 gesetzt und beim Leseaufruf die Zustände der Registereingänge in den RAM geschrieben. Anschließend wird von V-USB usbFunctionWrite bzw. usbFunctionRead je nach Reportgröße mehrmals aufgerufen. Im Read wird einfach nur der Inhalt des RAMs an den PC übertragen, beim Schreiben wird zuerst die Variable (die gleiche wie beim Lesen) gefüllt und nach dem letzten Wert vom PC die Methode processCommand aufgerufen. Dort findet das eigentliche Schreiben auf die Register statt. Zusätzlich zum simplen Schreiben kann man den Controller mit ein paar Logikfunktionen beauftragen. Diese werden immer mit der letzten Ausgabe verwurstet. Folgende Operationen sind möglich: * Überschreiben * OR * AND * XOR Zusätzlich kann man ein Flag zum Invertieren übergeben, dadurch werden die Funktionen NOR, NAND und XNOR sowie invertiertes Überschreiben ermöglicht. Mit einem weiteren Flag kann man die errechneten Werte ins EEProm des Controllers schreiben. Dadurch kann man direkt beim Einschalten der Hardware einen definierten Zustand ausgeben. Das einzige, das man in der Software noch anpassen muss, ist die Anzahl der jeweiligen Schieberegister. Oder einfach unverändert lassen - dann werden jeweils 8 Register angenommen. Ferner kann man eine ID in den EEProm schreiben, um mehrere (256) Devices zu unterscheiden. Diese ID wird bei jedem Lese-Vorgang im untersten Byte des Reports zurückgegeben. === PC === Auf dem PC kann eigentlich alles werkeln, was auf die entsprechenden Betriebssystem-APIs zugreifen kann. Ich beschränke mich auf Windows, die Portierung auf *nix/Mac/etc. sollte aber nicht allzu schwierig sein. Im Grunde muss man nicht viel machen, das Schwierigste dürfte wahrscheinlich das Finden des Devices sein. Ich habe im C#-Programm Teile aus der Wiimote-Lib von Brian Peek genommen. Ist das HID gefunden und ein Handler gesetzt, können mit HidD_SetFeature und -GetFeature Reports an den AVR gesendet oder von ihm angefordert werden. Wichtig ist hier eigentlich nur die Größe des übergebenen Arrays, bei falscher Länge kommt einfach nichts beim Device an! Man kann relativ viel Zeit damit verbringen, dort nach einem Fehler zu suchen, zumal sich ein vollbelegter Mikrocontroller (der nicht einmal UART hat) schlecht debuggen lässt. 3c2a284d0dfd69284478d770531e4fb14e38f373 347 345 2009-12-26T22:19:45Z Chris 2 Download-Link hinzugefügt wikitext text/x-wiki Die parallele Schnittstelle am PC ist tot. Nachdem sie schon vor einigen Jahren bei Notebooks verschwunden ist, findet man sie heute auch kaum noch bei Desktop-PCs. Selbst bei teureren Mainboards sind oft nur noch Pinheader vorhanden. Ein Slotblech dafür wird generell nicht geliefert. Die ganzen Drucker sind jetzt schneller und mit dünneren Leitungen per USB angebunden. Soweit, so gut. Nur wird die Luft für Bastler langsam dünner, wenn man keine größeren Ambitionen zu RS232 hat (deren Anschlüsse am PC auch langsam aussterben). Aus diesem Grund hatte ich die Idee, eine kleine Schaltung zu bauen, die zwar keinen Ersatz aber eine Alternative zum guten alten Parport darstellt. == Anforderungen == * Anbindung, die auch noch in ein paar Jahren funktioniert * Einfacher Aufbau * Einfach vom PC ansprechbar * Erweiterbar == Hardware == [[Bild:Usblotio_povray.jpg|thumb|Mit [http://www.povray.org/ POV-Ray] gerendertes Layout der Platinen]] Die Anbindung an den PC findet per USB statt. Hier soll (wieder einmal) [http://www.obdev.at/products/vusb/index-de.html V-USB] zum Einsatz kommen. Davon gibt es zwar schon ein Referenzdesign ([http://www.obdev.at/products/vusb/powerswitch.html PowerSwitch]), dieses hat meiner Meinung ein paar Schwachstellen: * keine Erweiterbarkeit * Treiber erforderlich (laufen die vorhandenen überhaupt unter Win7?) * relativ großer Aufbau Diesen Schwächen möchte ich mit einem ATTiny45 entgegenwirken. Dieser ist schön klein und braucht dank PLL (und automatischer Taktkalibrierung per USB) keinen externen Quarz. Damit man keine Treiber braucht, soll er sich dem Computer gegenüber als HID (Human Interface Device) ausgeben. Bleibt nur noch eines: Mit der Anbindung am PC bleiben nur noch 4 Pins am Tiny über - einer davon ist der Reset-Eingang - wie soll man da großartig Ausgänge schalten können? Ganz zu schweigen von der angestrebten Erweiterbarkeit... Die Lösung hierfür ist einfach: der Mikrocontroller steuert Schieberegister an, die beliebig kaskadiert werden können. So kann man quasi beliebig viele Ausgänge an den AVR dengeln. Als Ausgabeschieberegister dienen 74xx595, welche einen Latch haben und die Datenleitungen in einem Rutsch aktualisiert werden können. Um Signale auch lesen zu können, kommen 74xx165 zum Einsatz. Zwar haben diese auch einen Latch, allerdings ist dieser (anders als beim 595) low-aktiv. Damit wird's mit 4 I/Os am AVR eng. Gut, die Strobe-Leitungen muss man trennen, Clock kann gemeinsam laufen, nur sind jetzt schon alle Pins belegt. Es ist zwar möglich, die Daten ins Register zu laden, aber was bringen die Daten, wenn man sie nicht lesen kann? Mit einem kleinen Trick kann man das aber bewältigen: Die Datenleitungen beider Richtungen auf einen I/O. Zum Schutz des Ausganges des Registers gibt es aber einen Reihenwiderstand. Zwischen dem Lesen und Schreiben muss die Datenleitung einfach nur noch als Eingang bzw. Ausgang geschalten werden. Aber Vorsicht: dadurch, dass der Reset-Pin auch verwendet wird, kann der Mikrocontroller nur mit HVSP programmiert werden! (oder man lässt eine "Richtung" weg). == Software == === AVR === Wie bereits erwähnt läuft auf dem AVR objective developments V-USB als HID. Grundlage für meine Implementierung war das "Datastore"-Beispiel, das zusätzlich um die automatische Kalibrierung der CPU-Frequenz erweitert wurde. Da die USB-Schnittstelle zwangsläufig auf einem Interrupt-Pin hängt, der gleichzeitig auch für SPI verantwortlich ist, müssen die Schieberegister mit einem wesentlich langsameren Soft-SPI angesprochen werden. Der USB-Client reagiert bei dem Beginn einer Übertragung mit einem Aufruf der Methode usbFunctionSetup. In ihr wird dann entschieden, ob es sich um einen Schreib- oder Lesevorgang handelt. Hier wird zum einen die Speicheradresse auf 0 gesetzt und beim Leseaufruf die Zustände der Registereingänge in den RAM geschrieben. Anschließend wird von V-USB usbFunctionWrite bzw. usbFunctionRead je nach Reportgröße mehrmals aufgerufen. Im Read wird einfach nur der Inhalt des RAMs an den PC übertragen, beim Schreiben wird zuerst die Variable (die gleiche wie beim Lesen) gefüllt und nach dem letzten Wert vom PC die Methode processCommand aufgerufen. Dort findet das eigentliche Schreiben auf die Register statt. Zusätzlich zum simplen Schreiben kann man den Controller mit ein paar Logikfunktionen beauftragen. Diese werden immer mit der letzten Ausgabe verwurstet. Folgende Operationen sind möglich: * Überschreiben * OR * AND * XOR Zusätzlich kann man ein Flag zum Invertieren übergeben, dadurch werden die Funktionen NOR, NAND und XNOR sowie invertiertes Überschreiben ermöglicht. Mit einem weiteren Flag kann man die errechneten Werte ins EEProm des Controllers schreiben. Dadurch kann man direkt beim Einschalten der Hardware einen definierten Zustand ausgeben. Das einzige, das man in der Software noch anpassen muss, ist die Anzahl der jeweiligen Schieberegister. Oder einfach unverändert lassen - dann werden jeweils 8 Register angenommen. Ferner kann man eine ID in den EEProm schreiben, um mehrere (256) Devices zu unterscheiden. Diese ID wird bei jedem Lese-Vorgang im untersten Byte des Reports zurückgegeben. === PC === Auf dem PC kann eigentlich alles werkeln, was auf die entsprechenden Betriebssystem-APIs zugreifen kann. Ich beschränke mich auf Windows, die Portierung auf *nix/Mac/etc. sollte aber nicht allzu schwierig sein. Im Grunde muss man nicht viel machen, das Schwierigste dürfte wahrscheinlich das Finden des Devices sein. Ich habe im C#-Programm Teile aus der Wiimote-Lib von Brian Peek genommen. Ist das HID gefunden und ein Handler gesetzt, können mit HidD_SetFeature und -GetFeature Reports an den AVR gesendet oder von ihm angefordert werden. Wichtig ist hier eigentlich nur die Größe des übergebenen Arrays, bei falscher Länge kommt einfach nichts beim Device an! Man kann relativ viel Zeit damit verbringen, dort nach einem Fehler zu suchen, zumal sich ein vollbelegter Mikrocontroller (der nicht einmal UART hat) schlecht debuggen lässt. == Download == [[Datei:Usblotio.zip]] Firmware, EAGLE-Dateien und C#-Testprogramm a562ba0195b1fd556cd68d2a8841b1a334dd90c2 349 347 2009-12-26T23:35:04Z Chris 2 Ergänzungen, Bilder hinzugefügt wikitext text/x-wiki Die parallele Schnittstelle am PC ist tot. Nachdem sie schon vor einigen Jahren bei Notebooks verschwunden ist, findet man sie heute auch kaum noch bei Desktop-PCs. Selbst bei teureren Mainboards sind oft nur noch Pinheader vorhanden. Ein Slotblech dafür wird generell nicht geliefert. Die ganzen Drucker sind jetzt schneller und mit dünneren Leitungen per USB angebunden. Soweit, so gut. Nur wird die Luft für Bastler langsam dünner, wenn man keine größeren Ambitionen zu RS232 hat (deren Anschlüsse am PC auch langsam aussterben). Aus diesem Grund hatte ich die Idee, eine kleine Schaltung zu bauen, die zwar keinen Ersatz aber eine Alternative zum guten alten Parport darstellt. == Anforderungen == * Anbindung, die auch noch in ein paar Jahren funktioniert * Einfacher Aufbau * Einfach vom PC ansprechbar * Erweiterbar == Hardware == [[Bild:Usblotio_povray.jpg|thumb|Mit [http://www.povray.org/ POV-Ray] gerendertes Layout der Platinen]] [[Bild:Usblotio_main.jpg|thumb|Aufgebaute Hauptplatine des USBLotIO]] Die Anbindung an den PC findet per USB statt. Hier soll (wieder einmal) [http://www.obdev.at/products/vusb/index-de.html V-USB] zum Einsatz kommen. Davon gibt es zwar schon ein Referenzdesign ([http://www.obdev.at/products/vusb/powerswitch.html PowerSwitch]), dieses hat meiner Meinung ein paar Schwachstellen: * keine Erweiterbarkeit * Treiber erforderlich (laufen die vorhandenen überhaupt unter Win7?) * relativ großer Aufbau Diesen Schwächen möchte ich mit einem ATTiny45 entgegenwirken. Dieser ist schön klein und braucht dank PLL (und automatischer Taktkalibrierung per USB) keinen externen Quarz. Damit man keine Treiber braucht, soll er sich dem Computer gegenüber als HID (Human Interface Device) ausgeben. Bleibt nur noch eines: Mit der Anbindung am PC bleiben nur noch 4 Pins am Tiny über - einer davon ist der Reset-Eingang - wie soll man da großartig Ausgänge schalten können? Ganz zu schweigen von der angestrebten Erweiterbarkeit... Die Lösung hierfür ist einfach: der Mikrocontroller steuert Schieberegister an, die beliebig kaskadiert werden können. So kann man quasi beliebig viele Ausgänge an den AVR dengeln. Als Ausgabeschieberegister dienen 74xx595, welche einen Latch haben und die Datenleitungen in einem Rutsch aktualisiert werden können. Um Signale auch lesen zu können, kommen 74xx165 zum Einsatz. Zwar haben diese auch einen Latch, allerdings ist dieser (anders als beim 595) low-aktiv. Damit wird's mit 4 I/Os am AVR eng. Gut, die Strobe-Leitungen muss man trennen, Clock kann gemeinsam laufen, nur sind jetzt schon alle Pins belegt. Es ist zwar möglich, die Daten ins Register zu laden, aber was bringen die Daten, wenn man sie nicht lesen kann? Mit einem kleinen Trick kann man das aber bewältigen: Die Datenleitungen beider Richtungen auf einen I/O. Zum Schutz des Ausganges des Registers gibt es aber einen Reihenwiderstand. Zwischen dem Lesen und Schreiben muss die Datenleitung einfach nur noch als Eingang bzw. Ausgang geschaltet werden. Aber Vorsicht: dadurch, dass der Reset-Pin auch verwendet wird, kann der Mikrocontroller nur mit HVSP programmiert werden! (oder man lässt eine "Richtung" weg - noch ungetestet). <b style="color: red;">Ein Wort der Warnung sei noch angebracht:</b> Bei vielen PCs ist die USB-Schnittstelle NICHT abgesichert, bei einem Kurzschluss geht dann die komplette Leistung des Netzteils durch! Das kann zu zerstörten Leiterbahnen (sowohl am USB-Gerät als auch auf dem Mainboard) oder sogar Bränden führen! In der Firmware ist eine Stromaufnahme von 20mA angegeben, welche schon bei kleineren Aufbauten überschritten werden kann. Die Inbetriebnahme findet unter eigener Verantwortung statt! Rechnungen für neue Mainboards o.a. an mich werden mit Freude durch den Aktenvernichter gejagt. == Software == === AVR === Wie bereits erwähnt läuft auf dem AVR objective developments V-USB als HID. Grundlage für meine Implementierung war das "Datastore"-Beispiel, das zusätzlich um die automatische Kalibrierung der CPU-Frequenz erweitert wurde. Da die USB-Schnittstelle zwangsläufig auf einem Interrupt-Pin hängt, der gleichzeitig auch für SPI verantwortlich ist, müssen die Schieberegister mit einem wesentlich langsameren Soft-SPI angesprochen werden. Der USB-Client reagiert bei dem Beginn einer Übertragung mit einem Aufruf der Methode usbFunctionSetup. In ihr wird dann entschieden, ob es sich um einen Schreib- oder Lesevorgang handelt. Hier wird zum einen die Speicheradresse auf 0 gesetzt und beim Leseaufruf die Zustände der Registereingänge in den RAM geschrieben. Anschließend wird von V-USB usbFunctionWrite bzw. usbFunctionRead je nach Reportgröße mehrmals aufgerufen. Im Read wird einfach nur der Inhalt des RAMs an den PC übertragen, beim Schreiben wird zuerst die Variable (die gleiche wie beim Lesen) gefüllt und nach dem letzten Wert vom PC die Methode processCommand aufgerufen. Die übertragenen Werte werden in Anschlussreihenfolge aus Sicht der Hauptplatine angegeben. Gibt man z.B. 0x01 0x02 aus, wird am Ausgabemodul, das am nächsten zur Hauptplatine angeschlossen ist 0x01 ausgegeben, am "zweitnächsten" 0x02. Bei den Eingabemodulen verhält es sich genauso. Dort findet das eigentliche Schreiben auf die Register statt. Zusätzlich zum simplen Schreiben kann man den Controller mit ein paar Logikfunktionen beauftragen. Diese werden immer mit der letzten Ausgabe verarbeitet. Folgende Operationen sind möglich: * Überschreiben * OR * AND * XOR Zusätzlich kann man ein Flag zum Invertieren übergeben, dadurch werden die Funktionen NOR, NAND und XNOR sowie invertiertes Überschreiben ermöglicht. Mit einem weiteren Flag kann man die errechneten Werte ins EEProm des Controllers schreiben. Dadurch kann man direkt beim Einschalten der Hardware einen definierten Zustand ausgeben. Das einzige, das man in der Software noch anpassen muss, ist die Anzahl der jeweiligen Schieberegister. Oder einfach unverändert lassen - dann werden jeweils 8 Register angenommen. Diese Werte muss man nur anpassen, wenn man mehr als 8 Schieberegister verwendet oder mehr Performance (Auswirkung noch nicht geprüft) wünscht. Ferner kann man eine ID in den EEProm schreiben, um mehrere (256) Devices zu unterscheiden. Diese ID wird bei jedem Lese-Vorgang im untersten Byte des Reports zurückgegeben. === PC === Auf dem PC kann eigentlich alles werkeln, was auf die entsprechenden USB-APIs zugreifen kann. Ich beschränke mich auf Windows, die Portierung auf *nix/Mac/etc. sollte aber nicht allzu schwierig sein. Im Grunde muss man nicht viel machen, das Schwierigste dürfte wahrscheinlich das Finden des Devices sein. Ich habe im C#-Programm Teile aus der [http://www.brianpeek.com/blog/pages/wiimotelib.aspx WiimoteLib] von Brian Peek genommen. Ist das HID gefunden und ein Handler gesetzt, können mit HidD_SetFeature und -GetFeature Reports an den AVR gesendet oder von ihm angefordert werden. Wichtig ist hier eigentlich nur die Größe des übergebenen Arrays, bei falscher Länge kommt oft einfach nichts beim Device an! Man kann relativ viel Zeit damit verbringen, dort nach einem Fehler zu suchen, zumal sich ein vollbelegter Mikrocontroller (dessen UART man nicht verwenden kann) schlecht debuggen lässt. Zur Demonstration habe ich eine kleine Konsolen-Anwendung rund um die USBLotIO-Klasse geschrieben. Kann sein, dass ich die Klasse noch ein wenig umstrukturiere - die nullable Byte-Arrays gefallen mir nicht sonderlich. Im Ordner \csharp\USBlotIO\bin\Release\ befindet sich ein kleines Konsolenprogramm (USBlotIO.exe), mit dem man alle Features der Hardware testen/nutzen kann. Einfach einmal ohne Parameter starten, dann werden alle möglichen Aufrufe angezeigt (wem es beim Start per Doppelklick zu schnell geht: cmd starten und damit die Anwendung aufrufen). == Test == Die Hardwareinstallation ist im Baukastenprinzip. Module anstecken und per USB-Kabel mit dem PC verbinden. Nach wenigen Sekunden ist das Gerät bereit für die Verwendung. Leider konnte ich das Board für Eingabemodule nicht testen, da Reichelt keine 74xx165 in SMD hat. Auf dem Breadboard hat es funktioniert, dennoch gebe ich momentan keine 100%ige Garantie auf korrekte Funktion! Erfolgreich getestet wurde die C#-Anwendung bisher unter WinXP Pro SP3 sowie Windows 7. Für Vista brauche ich erst noch einen Probanden, Windows 2000 lasse ich außen vor (freue mich aber über Erfolgsmeldungen). == Download == [[Datei:Usblotio.zip]] Firmware, EAGLE-Dateien und C#-Testprogramm (VS2008, .NET 2.0) 8cac7e99a6253277183a39b531de77e0c4f72fd8 350 349 2009-12-26T23:41:07Z Chris 2 Kategorien mal wieder vergessen, Fuses müssen noch in den Text wikitext text/x-wiki Die parallele Schnittstelle am PC ist tot. Nachdem sie schon vor einigen Jahren bei Notebooks verschwunden ist, findet man sie heute auch kaum noch bei Desktop-PCs. Selbst bei teureren Mainboards sind oft nur noch Pinheader vorhanden. Ein Slotblech dafür wird generell nicht geliefert. Die ganzen Drucker sind jetzt schneller und mit dünneren Leitungen per USB angebunden. Soweit, so gut. Nur wird die Luft für Bastler langsam dünner, wenn man keine größeren Ambitionen zu RS232 hat (deren Anschlüsse am PC auch langsam aussterben). Aus diesem Grund hatte ich die Idee, eine kleine Schaltung zu bauen, die zwar keinen Ersatz aber eine Alternative zum guten alten Parport darstellt. == Anforderungen == * Anbindung, die auch noch in ein paar Jahren funktioniert * Einfacher Aufbau * Einfach vom PC ansprechbar * Erweiterbar == Hardware == [[Bild:Usblotio_povray.jpg|thumb|Mit [http://www.povray.org/ POV-Ray] gerendertes Layout der Platinen]] [[Bild:Usblotio_main.jpg|thumb|Aufgebaute Hauptplatine des USBLotIO]] Die Anbindung an den PC findet per USB statt. Hier soll (wieder einmal) [http://www.obdev.at/products/vusb/index-de.html V-USB] zum Einsatz kommen. Davon gibt es zwar schon ein Referenzdesign ([http://www.obdev.at/products/vusb/powerswitch.html PowerSwitch]), dieses hat meiner Meinung ein paar Schwachstellen: * keine Erweiterbarkeit * Treiber erforderlich (laufen die vorhandenen überhaupt unter Win7?) * relativ großer Aufbau Diesen Schwächen möchte ich mit einem ATTiny45 entgegenwirken. Dieser ist schön klein und braucht dank PLL (und automatischer Taktkalibrierung per USB) keinen externen Quarz. Damit man keine Treiber braucht, soll er sich dem Computer gegenüber als HID (Human Interface Device) ausgeben. Bleibt nur noch eines: Mit der Anbindung am PC bleiben nur noch 4 Pins am Tiny über - einer davon ist der Reset-Eingang - wie soll man da großartig Ausgänge schalten können? Ganz zu schweigen von der angestrebten Erweiterbarkeit... Die Lösung hierfür ist einfach: der Mikrocontroller steuert Schieberegister an, die beliebig kaskadiert werden können. So kann man quasi beliebig viele Ausgänge an den AVR dengeln. Als Ausgabeschieberegister dienen 74xx595, welche einen Latch haben und die Datenleitungen in einem Rutsch aktualisiert werden können. Um Signale auch lesen zu können, kommen 74xx165 zum Einsatz. Zwar haben diese auch einen Latch, allerdings ist dieser (anders als beim 595) low-aktiv. Damit wird's mit 4 I/Os am AVR eng. Gut, die Strobe-Leitungen muss man trennen, Clock kann gemeinsam laufen, nur sind jetzt schon alle Pins belegt. Es ist zwar möglich, die Daten ins Register zu laden, aber was bringen die Daten, wenn man sie nicht lesen kann? Mit einem kleinen Trick kann man das aber bewältigen: Die Datenleitungen beider Richtungen auf einen I/O. Zum Schutz des Ausganges des Registers gibt es aber einen Reihenwiderstand. Zwischen dem Lesen und Schreiben muss die Datenleitung einfach nur noch als Eingang bzw. Ausgang geschaltet werden. Aber Vorsicht: dadurch, dass der Reset-Pin auch verwendet wird, kann der Mikrocontroller nur mit HVSP programmiert werden! (oder man lässt eine "Richtung" weg - noch ungetestet). <b style="color: red;">Ein Wort der Warnung sei noch angebracht:</b> Bei vielen PCs ist die USB-Schnittstelle NICHT abgesichert, bei einem Kurzschluss geht dann die komplette Leistung des Netzteils durch! Das kann zu zerstörten Leiterbahnen (sowohl am USB-Gerät als auch auf dem Mainboard) oder sogar Bränden führen! In der Firmware ist eine Stromaufnahme von 20mA angegeben, welche schon bei kleineren Aufbauten überschritten werden kann. Die Inbetriebnahme findet unter eigener Verantwortung statt! Rechnungen für neue Mainboards o.a. an mich werden mit Freude durch den Aktenvernichter gejagt. == Software == === AVR === Wie bereits erwähnt läuft auf dem AVR objective developments V-USB als HID. Grundlage für meine Implementierung war das "Datastore"-Beispiel, das zusätzlich um die automatische Kalibrierung der CPU-Frequenz erweitert wurde. Da die USB-Schnittstelle zwangsläufig auf einem Interrupt-Pin hängt, der gleichzeitig auch für SPI verantwortlich ist, müssen die Schieberegister mit einem wesentlich langsameren Soft-SPI angesprochen werden. Der USB-Client reagiert bei dem Beginn einer Übertragung mit einem Aufruf der Methode usbFunctionSetup. In ihr wird dann entschieden, ob es sich um einen Schreib- oder Lesevorgang handelt. Hier wird zum einen die Speicheradresse auf 0 gesetzt und beim Leseaufruf die Zustände der Registereingänge in den RAM geschrieben. Anschließend wird von V-USB usbFunctionWrite bzw. usbFunctionRead je nach Reportgröße mehrmals aufgerufen. Im Read wird einfach nur der Inhalt des RAMs an den PC übertragen, beim Schreiben wird zuerst die Variable (die gleiche wie beim Lesen) gefüllt und nach dem letzten Wert vom PC die Methode processCommand aufgerufen. Die übertragenen Werte werden in Anschlussreihenfolge aus Sicht der Hauptplatine angegeben. Gibt man z.B. 0x01 0x02 aus, wird am Ausgabemodul, das am nächsten zur Hauptplatine angeschlossen ist 0x01 ausgegeben, am "zweitnächsten" 0x02. Bei den Eingabemodulen verhält es sich genauso. Dort findet das eigentliche Schreiben auf die Register statt. Zusätzlich zum simplen Schreiben kann man den Controller mit ein paar Logikfunktionen beauftragen. Diese werden immer mit der letzten Ausgabe verarbeitet. Folgende Operationen sind möglich: * Überschreiben * OR * AND * XOR Zusätzlich kann man ein Flag zum Invertieren übergeben, dadurch werden die Funktionen NOR, NAND und XNOR sowie invertiertes Überschreiben ermöglicht. Mit einem weiteren Flag kann man die errechneten Werte ins EEProm des Controllers schreiben. Dadurch kann man direkt beim Einschalten der Hardware einen definierten Zustand ausgeben. Das einzige, das man in der Software noch anpassen muss, ist die Anzahl der jeweiligen Schieberegister. Oder einfach unverändert lassen - dann werden jeweils 8 Register angenommen. Diese Werte muss man nur anpassen, wenn man mehr als 8 Schieberegister verwendet oder mehr Performance (Auswirkung noch nicht geprüft) wünscht. Ferner kann man eine ID in den EEProm schreiben, um mehrere (256) Devices zu unterscheiden. Diese ID wird bei jedem Lese-Vorgang im untersten Byte des Reports zurückgegeben. (TODO: Fuses im AVR) === PC === Auf dem PC kann eigentlich alles werkeln, was auf die entsprechenden USB-APIs zugreifen kann. Ich beschränke mich auf Windows, die Portierung auf *nix/Mac/etc. sollte aber nicht allzu schwierig sein. Im Grunde muss man nicht viel machen, das Schwierigste dürfte wahrscheinlich das Finden des Devices sein. Ich habe im C#-Programm Teile aus der [http://www.brianpeek.com/blog/pages/wiimotelib.aspx WiimoteLib] von Brian Peek genommen. Ist das HID gefunden und ein Handler gesetzt, können mit HidD_SetFeature und -GetFeature Reports an den AVR gesendet oder von ihm angefordert werden. Wichtig ist hier eigentlich nur die Größe des übergebenen Arrays, bei falscher Länge kommt oft einfach nichts beim Device an! Man kann relativ viel Zeit damit verbringen, dort nach einem Fehler zu suchen, zumal sich ein vollbelegter Mikrocontroller (dessen UART man nicht verwenden kann) schlecht debuggen lässt. Zur Demonstration habe ich eine kleine Konsolen-Anwendung rund um die USBLotIO-Klasse geschrieben. Kann sein, dass ich die Klasse noch ein wenig umstrukturiere - die nullable Byte-Arrays gefallen mir nicht sonderlich. Im Ordner \csharp\USBlotIO\bin\Release\ befindet sich ein kleines Konsolenprogramm (USBlotIO.exe), mit dem man alle Features der Hardware testen/nutzen kann. Einfach einmal ohne Parameter starten, dann werden alle möglichen Aufrufe angezeigt (wem es beim Start per Doppelklick zu schnell geht: cmd starten und damit die Anwendung aufrufen). == Test == Die Hardwareinstallation ist im Baukastenprinzip. Module anstecken und per USB-Kabel mit dem PC verbinden. Nach wenigen Sekunden ist das Gerät bereit für die Verwendung. Leider konnte ich das Board für Eingabemodule nicht testen, da Reichelt keine 74xx165 in SMD hat. Auf dem Breadboard hat es funktioniert, dennoch gebe ich momentan keine 100%ige Garantie auf korrekte Funktion! Erfolgreich getestet wurde die C#-Anwendung bisher unter WinXP Pro SP3 sowie Windows 7. Für Vista brauche ich erst noch einen Probanden, Windows 2000 lasse ich außen vor (freue mich aber über Erfolgsmeldungen). == Download == [[Datei:Usblotio.zip]] Firmware, EAGLE-Dateien und C#-Testprogramm (VS2008, .NET 2.0) [[Category:AVR]] [[Category:USB]] [[Category:PC]] 297961c2479d79b7164e63d476b413c944e9637d 354 350 2009-12-27T22:33:38Z Chris 2 Infos zu Fuses hinzugefügt wikitext text/x-wiki Die parallele Schnittstelle am PC ist tot. Nachdem sie schon vor einigen Jahren bei Notebooks verschwunden ist, findet man sie heute auch kaum noch bei Desktop-PCs. Selbst bei teureren Mainboards sind oft nur noch Pinheader vorhanden. Ein Slotblech dafür wird generell nicht geliefert. Die ganzen Drucker sind jetzt schneller und mit dünneren Leitungen per USB angebunden. Soweit, so gut. Nur wird die Luft für Bastler langsam dünner, wenn man keine größeren Ambitionen zu RS232 hat (deren Anschlüsse am PC auch langsam aussterben). Aus diesem Grund hatte ich die Idee, eine kleine Schaltung zu bauen, die zwar keinen Ersatz aber eine Alternative zum guten alten Parport darstellt. == Anforderungen == * Anbindung, die auch noch in ein paar Jahren funktioniert * Einfacher Aufbau * Einfach vom PC ansprechbar * Erweiterbar == Hardware == [[Bild:Usblotio_povray.jpg|thumb|Mit [http://www.povray.org/ POV-Ray] gerendertes Layout der Platinen]] [[Bild:Usblotio_main.jpg|thumb|Aufgebaute Hauptplatine des USBLotIO]] Die Anbindung an den PC findet per USB statt. Hier soll (wieder einmal) [http://www.obdev.at/products/vusb/index-de.html V-USB] zum Einsatz kommen. Davon gibt es zwar schon ein Referenzdesign ([http://www.obdev.at/products/vusb/powerswitch.html PowerSwitch]), dieses hat meiner Meinung ein paar Schwachstellen: * keine Erweiterbarkeit * Treiber erforderlich (laufen die vorhandenen überhaupt unter Win7?) * relativ großer Aufbau Diesen Schwächen möchte ich mit einem ATTiny45 entgegenwirken. Dieser ist schön klein und braucht dank PLL (und automatischer Taktkalibrierung per USB) keinen externen Quarz. Damit man keine Treiber braucht, soll er sich dem Computer gegenüber als HID (Human Interface Device) ausgeben. Bleibt nur noch eines: Mit der Anbindung am PC bleiben nur noch 4 Pins am Tiny über - einer davon ist der Reset-Eingang - wie soll man da großartig Ausgänge schalten können? Ganz zu schweigen von der angestrebten Erweiterbarkeit... Die Lösung hierfür ist einfach: der Mikrocontroller steuert Schieberegister an, die beliebig kaskadiert werden können. So kann man quasi beliebig viele Ausgänge an den AVR dengeln. Als Ausgabeschieberegister dienen 74xx595, welche einen Latch haben und die Datenleitungen in einem Rutsch aktualisiert werden können. Um Signale auch lesen zu können, kommen 74xx165 zum Einsatz. Zwar haben diese auch einen Latch, allerdings ist dieser (anders als beim 595) low-aktiv. Damit wird's mit 4 I/Os am AVR eng. Gut, die Strobe-Leitungen muss man trennen, Clock kann gemeinsam laufen, nur sind jetzt schon alle Pins belegt. Es ist zwar möglich, die Daten ins Register zu laden, aber was bringen die Daten, wenn man sie nicht lesen kann? Mit einem kleinen Trick kann man das aber bewältigen: Die Datenleitungen beider Richtungen auf einen I/O. Zum Schutz des Ausganges des Registers gibt es aber einen Reihenwiderstand. Zwischen dem Lesen und Schreiben muss die Datenleitung einfach nur noch als Eingang bzw. Ausgang geschaltet werden. Aber Vorsicht: dadurch, dass der Reset-Pin auch verwendet wird, kann der Mikrocontroller nur mit HVSP programmiert werden! (oder man lässt eine "Richtung" weg - noch ungetestet). <b style="color: red;">Ein Wort der Warnung sei noch angebracht:</b> Bei vielen PCs ist die USB-Schnittstelle NICHT abgesichert, bei einem Kurzschluss geht dann die komplette Leistung des Netzteils durch! Das kann zu zerstörten Leiterbahnen (sowohl am USB-Gerät als auch auf dem Mainboard) oder sogar Bränden führen! In der Firmware ist eine Stromaufnahme von 20mA angegeben, welche schon bei kleineren Aufbauten überschritten werden kann. Die Inbetriebnahme findet unter eigener Verantwortung statt! Rechnungen für neue Mainboards o.a. an mich werden mit Freude durch den Aktenvernichter gejagt. == Software == === AVR === Wie bereits erwähnt läuft auf dem AVR objective developments V-USB als HID. Grundlage für meine Implementierung war das "Datastore"-Beispiel, das zusätzlich um die automatische Kalibrierung der CPU-Frequenz erweitert wurde. Da die USB-Schnittstelle zwangsläufig auf einem Interrupt-Pin hängt, der gleichzeitig auch für SPI verantwortlich ist, müssen die Schieberegister mit einem wesentlich langsameren Soft-SPI angesprochen werden. Der USB-Client reagiert bei dem Beginn einer Übertragung mit einem Aufruf der Methode usbFunctionSetup. In ihr wird dann entschieden, ob es sich um einen Schreib- oder Lesevorgang handelt. Hier wird zum einen die Speicheradresse auf 0 gesetzt und beim Leseaufruf die Zustände der Registereingänge in den RAM geschrieben. Anschließend wird von V-USB usbFunctionWrite bzw. usbFunctionRead je nach Reportgröße mehrmals aufgerufen. Im Read wird einfach nur der Inhalt des RAMs an den PC übertragen, beim Schreiben wird zuerst die Variable (die gleiche wie beim Lesen) gefüllt und nach dem letzten Wert vom PC die Methode processCommand aufgerufen. Die übertragenen Werte werden in Anschlussreihenfolge aus Sicht der Hauptplatine angegeben. Gibt man z.B. 0x01 0x02 aus, wird am Ausgabemodul, das am nächsten zur Hauptplatine angeschlossen ist 0x01 ausgegeben, am "zweitnächsten" 0x02. Bei den Eingabemodulen verhält es sich genauso. Dort findet das eigentliche Schreiben auf die Register statt. Zusätzlich zum simplen Schreiben kann man den Controller mit ein paar Logikfunktionen beauftragen. Diese werden immer mit der letzten Ausgabe verarbeitet. Folgende Operationen sind möglich: * Überschreiben * OR * AND * XOR Zusätzlich kann man ein Flag zum Invertieren übergeben, dadurch werden die Funktionen NOR, NAND und XNOR sowie invertiertes Überschreiben ermöglicht. Mit einem weiteren Flag kann man die errechneten Werte ins EEProm des Controllers schreiben. Dadurch kann man direkt beim Einschalten der Hardware einen definierten Zustand ausgeben. Das einzige, das man in der Software noch anpassen muss, ist die Anzahl der jeweiligen Schieberegister. Oder einfach unverändert lassen - dann werden jeweils 8 Register angenommen. Diese Werte muss man nur anpassen, wenn man mehr als 8 Schieberegister verwendet oder mehr Performance (Auswirkung noch nicht geprüft) wünscht. Ferner kann man eine ID in den EEProm schreiben, um mehrere (256) Devices zu unterscheiden. Diese ID wird bei jedem Lese-Vorgang im untersten Byte des Reports zurückgegeben. [[Bild:Usblotio_fuses.png|thumb|Im AVR programmierte Fuses]] Damit man die Hardware vollständig genutzt werden kann, müssen die Fuses wie folgt programmiert werden (siehe auch Screenshot): * Extended: 0xFF * High: 0x75 * Low: 0xE1 SPIEN kann nur deaktiviert werden, wenn man per HVSP programmiert, RSTDISBL ''sollte'' eigentlich reichen, habe ich allerdings nicht ausprobiert ;-) === PC === Auf dem PC kann eigentlich alles werkeln, was auf die entsprechenden USB-APIs zugreifen kann. Ich beschränke mich auf Windows, die Portierung auf *nix/Mac/etc. sollte aber nicht allzu schwierig sein. Im Grunde muss man nicht viel machen, das Schwierigste dürfte wahrscheinlich das Finden des Devices sein. Ich habe im C#-Programm Teile aus der [http://www.brianpeek.com/blog/pages/wiimotelib.aspx WiimoteLib] von Brian Peek genommen. Ist das HID gefunden und ein Handler gesetzt, können mit HidD_SetFeature und -GetFeature Reports an den AVR gesendet oder von ihm angefordert werden. Wichtig ist hier eigentlich nur die Größe des übergebenen Arrays, bei falscher Länge kommt oft einfach nichts beim Device an! Man kann relativ viel Zeit damit verbringen, dort nach einem Fehler zu suchen, zumal sich ein vollbelegter Mikrocontroller (dessen UART man nicht verwenden kann) schlecht debuggen lässt. Zur Demonstration habe ich eine kleine Konsolen-Anwendung rund um die USBLotIO-Klasse geschrieben. Kann sein, dass ich die Klasse noch ein wenig umstrukturiere - die nullable Byte-Arrays gefallen mir nicht sonderlich. Im Ordner \csharp\USBlotIO\bin\Release\ befindet sich ein kleines Konsolenprogramm (USBlotIO.exe), mit dem man alle Features der Hardware testen/nutzen kann. Einfach einmal ohne Parameter starten, dann werden alle möglichen Aufrufe angezeigt (wem es beim Start per Doppelklick zu schnell geht: cmd starten und damit die Anwendung aufrufen). == Test == Die Hardwareinstallation ist im Baukastenprinzip. Module anstecken und per USB-Kabel mit dem PC verbinden. Nach wenigen Sekunden ist das Gerät bereit für die Verwendung. Leider konnte ich das Board für Eingabemodule nicht testen, da Reichelt keine 74xx165 in SMD hat. Auf dem Breadboard hat es funktioniert, dennoch gebe ich momentan keine 100%ige Garantie auf korrekte Funktion! Erfolgreich getestet wurde die C#-Anwendung bisher unter WinXP Pro SP3 sowie Windows 7. Für Vista brauche ich erst noch einen Probanden, Windows 2000 lasse ich außen vor (freue mich aber über Erfolgsmeldungen). == Download == [[Datei:Usblotio.zip]] Firmware, EAGLE-Dateien und C#-Testprogramm (VS2008, .NET 2.0) [[Category:AVR]] [[Category:USB]] [[Category:PC]] 622370652491b4707322e88d5f5f108532d5ba9c 356 354 2009-12-27T22:47:15Z Chris 2 Bild des Ausgabemoduls hinzugefügt wikitext text/x-wiki Die parallele Schnittstelle am PC ist tot. Nachdem sie schon vor einigen Jahren bei Notebooks verschwunden ist, findet man sie heute auch kaum noch bei Desktop-PCs. Selbst bei teureren Mainboards sind oft nur noch Pinheader vorhanden. Ein Slotblech dafür wird generell nicht geliefert. Die ganzen Drucker sind jetzt schneller und mit dünneren Leitungen per USB angebunden. Soweit, so gut. Nur wird die Luft für Bastler langsam dünner, wenn man keine größeren Ambitionen zu RS232 hat (deren Anschlüsse am PC auch langsam aussterben). Aus diesem Grund hatte ich die Idee, eine kleine Schaltung zu bauen, die zwar keinen Ersatz aber eine Alternative zum guten alten Parport darstellt. == Anforderungen == * Anbindung, die auch noch in ein paar Jahren funktioniert * Einfacher Aufbau * Einfach vom PC ansprechbar * Erweiterbar == Hardware == [[Bild:Usblotio_povray.jpg|thumb|Mit [http://www.povray.org/ POV-Ray] gerendertes Layout der Platinen]] [[Bild:Usblotio_main.jpg|thumb|Aufgebaute Hauptplatine des USBLotIO]] [[Bild:Usblotio out.jpg|thumb|Aufgebautes Ausgabemodul]] Die Anbindung an den PC findet per USB statt. Hier soll (wieder einmal) [http://www.obdev.at/products/vusb/index-de.html V-USB] zum Einsatz kommen. Davon gibt es zwar schon ein Referenzdesign ([http://www.obdev.at/products/vusb/powerswitch.html PowerSwitch]), dieses hat meiner Meinung ein paar Schwachstellen: * keine Erweiterbarkeit * Treiber erforderlich (laufen die vorhandenen überhaupt unter Win7?) * relativ großer Aufbau Diesen Schwächen möchte ich mit einem ATTiny45 entgegenwirken. Dieser ist schön klein und braucht dank PLL (und automatischer Taktkalibrierung per USB) keinen externen Quarz. Damit man keine Treiber braucht, soll er sich dem Computer gegenüber als HID (Human Interface Device) ausgeben. Bleibt nur noch eines: Mit der Anbindung am PC bleiben nur noch 4 Pins am Tiny über - einer davon ist der Reset-Eingang - wie soll man da großartig Ausgänge schalten können? Ganz zu schweigen von der angestrebten Erweiterbarkeit... Die Lösung hierfür ist einfach: der Mikrocontroller steuert Schieberegister an, die beliebig kaskadiert werden können. So kann man quasi beliebig viele Ausgänge an den AVR dengeln. Als Ausgabeschieberegister dienen 74xx595, welche einen Latch haben und die Datenleitungen in einem Rutsch aktualisiert werden können. Um Signale auch lesen zu können, kommen 74xx165 zum Einsatz. Zwar haben diese auch einen Latch, allerdings ist dieser (anders als beim 595) low-aktiv. Damit wird's mit 4 I/Os am AVR eng. Gut, die Strobe-Leitungen muss man trennen, Clock kann gemeinsam laufen, nur sind jetzt schon alle Pins belegt. Es ist zwar möglich, die Daten ins Register zu laden, aber was bringen die Daten, wenn man sie nicht lesen kann? Mit einem kleinen Trick kann man das aber bewältigen: Die Datenleitungen beider Richtungen auf einen I/O. Zum Schutz des Ausganges des Registers gibt es aber einen Reihenwiderstand. Zwischen dem Lesen und Schreiben muss die Datenleitung einfach nur noch als Eingang bzw. Ausgang geschaltet werden. Aber Vorsicht: dadurch, dass der Reset-Pin auch verwendet wird, kann der Mikrocontroller nur mit HVSP programmiert werden! (oder man lässt eine "Richtung" weg - noch ungetestet). <b style="color: red;">Ein Wort der Warnung sei noch angebracht:</b> Bei vielen PCs ist die USB-Schnittstelle NICHT abgesichert, bei einem Kurzschluss geht dann die komplette Leistung des Netzteils durch! Das kann zu zerstörten Leiterbahnen (sowohl am USB-Gerät als auch auf dem Mainboard) oder sogar Bränden führen! In der Firmware ist eine Stromaufnahme von 20mA angegeben, welche schon bei kleineren Aufbauten überschritten werden kann. Die Inbetriebnahme findet unter eigener Verantwortung statt! Rechnungen für neue Mainboards o.a. an mich werden mit Freude durch den Aktenvernichter gejagt. == Software == === AVR === Wie bereits erwähnt läuft auf dem AVR objective developments V-USB als HID. Grundlage für meine Implementierung war das "Datastore"-Beispiel, das zusätzlich um die automatische Kalibrierung der CPU-Frequenz erweitert wurde. Da die USB-Schnittstelle zwangsläufig auf einem Interrupt-Pin hängt, der gleichzeitig auch für SPI verantwortlich ist, müssen die Schieberegister mit einem wesentlich langsameren Soft-SPI angesprochen werden. Der USB-Client reagiert bei dem Beginn einer Übertragung mit einem Aufruf der Methode usbFunctionSetup. In ihr wird dann entschieden, ob es sich um einen Schreib- oder Lesevorgang handelt. Hier wird zum einen die Speicheradresse auf 0 gesetzt und beim Leseaufruf die Zustände der Registereingänge in den RAM geschrieben. Anschließend wird von V-USB usbFunctionWrite bzw. usbFunctionRead je nach Reportgröße mehrmals aufgerufen. Im Read wird einfach nur der Inhalt des RAMs an den PC übertragen, beim Schreiben wird zuerst die Variable (die gleiche wie beim Lesen) gefüllt und nach dem letzten Wert vom PC die Methode processCommand aufgerufen. Die übertragenen Werte werden in Anschlussreihenfolge aus Sicht der Hauptplatine angegeben. Gibt man z.B. 0x01 0x02 aus, wird am Ausgabemodul, das am nächsten zur Hauptplatine angeschlossen ist 0x01 ausgegeben, am "zweitnächsten" 0x02. Bei den Eingabemodulen verhält es sich genauso. Dort findet das eigentliche Schreiben auf die Register statt. Zusätzlich zum simplen Schreiben kann man den Controller mit ein paar Logikfunktionen beauftragen. Diese werden immer mit der letzten Ausgabe verarbeitet. Folgende Operationen sind möglich: * Überschreiben * OR * AND * XOR Zusätzlich kann man ein Flag zum Invertieren übergeben, dadurch werden die Funktionen NOR, NAND und XNOR sowie invertiertes Überschreiben ermöglicht. Mit einem weiteren Flag kann man die errechneten Werte ins EEProm des Controllers schreiben. Dadurch kann man direkt beim Einschalten der Hardware einen definierten Zustand ausgeben. Das einzige, das man in der Software noch anpassen muss, ist die Anzahl der jeweiligen Schieberegister. Oder einfach unverändert lassen - dann werden jeweils 8 Register angenommen. Diese Werte muss man nur anpassen, wenn man mehr als 8 Schieberegister verwendet oder mehr Performance (Auswirkung noch nicht geprüft) wünscht. Ferner kann man eine ID in den EEProm schreiben, um mehrere (256) Devices zu unterscheiden. Diese ID wird bei jedem Lese-Vorgang im untersten Byte des Reports zurückgegeben. [[Bild:Usblotio_fuses.png|thumb|Im AVR programmierte Fuses]] Damit man die Hardware vollständig genutzt werden kann, müssen die Fuses wie folgt programmiert werden (siehe auch Screenshot): * Extended: 0xFF * High: 0x75 * Low: 0xE1 SPIEN kann nur deaktiviert werden, wenn man per HVSP programmiert, RSTDISBL ''sollte'' eigentlich reichen, habe ich allerdings nicht ausprobiert ;-) === PC === Auf dem PC kann eigentlich alles werkeln, was auf die entsprechenden USB-APIs zugreifen kann. Ich beschränke mich auf Windows, die Portierung auf *nix/Mac/etc. sollte aber nicht allzu schwierig sein. Im Grunde muss man nicht viel machen, das Schwierigste dürfte wahrscheinlich das Finden des Devices sein. Ich habe im C#-Programm Teile aus der [http://www.brianpeek.com/blog/pages/wiimotelib.aspx WiimoteLib] von Brian Peek genommen. Ist das HID gefunden und ein Handler gesetzt, können mit HidD_SetFeature und -GetFeature Reports an den AVR gesendet oder von ihm angefordert werden. Wichtig ist hier eigentlich nur die Größe des übergebenen Arrays, bei falscher Länge kommt oft einfach nichts beim Device an! Man kann relativ viel Zeit damit verbringen, dort nach einem Fehler zu suchen, zumal sich ein vollbelegter Mikrocontroller (dessen UART man nicht verwenden kann) schlecht debuggen lässt. Zur Demonstration habe ich eine kleine Konsolen-Anwendung rund um die USBLotIO-Klasse geschrieben. Kann sein, dass ich die Klasse noch ein wenig umstrukturiere - die nullable Byte-Arrays gefallen mir nicht sonderlich. Im Ordner \csharp\USBlotIO\bin\Release\ befindet sich ein kleines Konsolenprogramm (USBlotIO.exe), mit dem man alle Features der Hardware testen/nutzen kann. Einfach einmal ohne Parameter starten, dann werden alle möglichen Aufrufe angezeigt (wem es beim Start per Doppelklick zu schnell geht: cmd starten und damit die Anwendung aufrufen). == Test == Die Hardwareinstallation ist im Baukastenprinzip. Module anstecken und per USB-Kabel mit dem PC verbinden. Nach wenigen Sekunden ist das Gerät bereit für die Verwendung. Leider konnte ich das Board für Eingabemodule nicht testen, da Reichelt keine 74xx165 in SMD hat. Auf dem Breadboard hat es funktioniert, dennoch gebe ich momentan keine 100%ige Garantie auf korrekte Funktion! Erfolgreich getestet wurde die C#-Anwendung bisher unter WinXP Pro SP3 sowie Windows 7. Für Vista brauche ich erst noch einen Probanden, Windows 2000 lasse ich außen vor (freue mich aber über Erfolgsmeldungen). == Download == [[Datei:Usblotio.zip]] Firmware, EAGLE-Dateien und C#-Testprogramm (VS2008, .NET 2.0) [[Category:AVR]] [[Category:USB]] [[Category:PC]] 8f2c3098db9e1bae8b603d56342eb3049528b666 387 356 2010-02-28T19:25:40Z Chris 2 Stromlaufplan hinzugefügt, Board-Bildchen in Gallery gepackt wikitext text/x-wiki Die parallele Schnittstelle am PC ist tot. Nachdem sie schon vor einigen Jahren bei Notebooks verschwunden ist, findet man sie heute auch kaum noch bei Desktop-PCs. Selbst bei teureren Mainboards sind oft nur noch Pinheader vorhanden. Ein Slotblech dafür wird generell nicht geliefert. Die ganzen Drucker sind jetzt schneller und mit dünneren Leitungen per USB angebunden. Soweit, so gut. Nur wird die Luft für Bastler langsam dünner, wenn man keine größeren Ambitionen zu RS232 hat (deren Anschlüsse am PC auch langsam aussterben). Aus diesem Grund hatte ich die Idee, eine kleine Schaltung zu bauen, die zwar keinen Ersatz aber eine Alternative zum guten alten Parport darstellt. == Anforderungen == * Anbindung, die auch noch in ein paar Jahren funktioniert * Einfacher Aufbau * Einfach vom PC ansprechbar * Erweiterbar == Hardware == [[Bild:Usblotio_sch.png|thumb|Stromlaufplan der Platinen]] Die Anbindung an den PC findet per USB statt. Hier soll (wieder einmal) [http://www.obdev.at/products/vusb/index-de.html V-USB] zum Einsatz kommen. Davon gibt es zwar schon ein Referenzdesign ([http://www.obdev.at/products/vusb/powerswitch.html PowerSwitch]), dieses hat meiner Meinung ein paar Schwachstellen: * keine Erweiterbarkeit * Treiber erforderlich (laufen die vorhandenen überhaupt unter Win7?) * relativ großer Aufbau Diesen Schwächen möchte ich mit einem ATTiny45 entgegenwirken. Dieser ist schön klein und braucht dank PLL (und automatischer Taktkalibrierung per USB) keinen externen Quarz. Damit man keine Treiber braucht, soll er sich dem Computer gegenüber als HID (Human Interface Device) ausgeben. Bleibt nur noch eines: Mit der Anbindung am PC bleiben nur noch 4 Pins am Tiny über - einer davon ist der Reset-Eingang - wie soll man da großartig Ausgänge schalten können? Ganz zu schweigen von der angestrebten Erweiterbarkeit... Die Lösung hierfür ist einfach: der Mikrocontroller steuert Schieberegister an, die beliebig kaskadiert werden können. So kann man quasi beliebig viele Ausgänge an den AVR dengeln. Als Ausgabeschieberegister dienen 74xx595, welche einen Latch haben und die Datenleitungen in einem Rutsch aktualisiert werden können. Um Signale auch lesen zu können, kommen 74xx165 zum Einsatz. Zwar haben diese auch einen Latch, allerdings ist dieser (anders als beim 595) low-aktiv. Damit wird's mit 4 I/Os am AVR eng. Gut, die Strobe-Leitungen muss man trennen, Clock kann gemeinsam laufen, nur sind jetzt schon alle Pins belegt. Es ist zwar möglich, die Daten ins Register zu laden, aber was bringen die Daten, wenn man sie nicht lesen kann? Mit einem kleinen Trick kann man das aber bewältigen: Die Datenleitungen beider Richtungen auf einen I/O. Zum Schutz des Ausganges des Registers gibt es aber einen Reihenwiderstand. Zwischen dem Lesen und Schreiben muss die Datenleitung einfach nur noch als Eingang bzw. Ausgang geschaltet werden. <gallery> Bild:Usblotio_povray.jpg|Mit [http://www.povray.org/ POV-Ray] gerendertes Layout der Platinen Bild:Usblotio_main.jpg|Aufgebaute Hauptplatine des USBLotIO Bild:Usblotio out.jpg|Aufgebautes Ausgabemodul </gallery> Aber Vorsicht: dadurch, dass der Reset-Pin auch verwendet wird, kann der Mikrocontroller nur mit HVSP programmiert werden! (oder man lässt eine "Richtung" weg - noch ungetestet). <b style="color: red;">Ein Wort der Warnung sei noch angebracht:</b> Bei vielen PCs ist die USB-Schnittstelle NICHT abgesichert, bei einem Kurzschluss geht dann die komplette Leistung des Netzteils durch! Das kann zu zerstörten Leiterbahnen (sowohl am USB-Gerät als auch auf dem Mainboard) oder sogar Bränden führen! In der Firmware ist eine Stromaufnahme von 20mA angegeben, welche schon bei kleineren Aufbauten überschritten werden kann. Die Inbetriebnahme findet unter eigener Verantwortung statt! Rechnungen für neue Mainboards o.a. an mich werden mit Freude durch den Aktenvernichter gejagt. == Software == === AVR === Wie bereits erwähnt läuft auf dem AVR objective developments V-USB als HID. Grundlage für meine Implementierung war das "Datastore"-Beispiel, das zusätzlich um die automatische Kalibrierung der CPU-Frequenz erweitert wurde. Da die USB-Schnittstelle zwangsläufig auf einem Interrupt-Pin hängt, der gleichzeitig auch für SPI verantwortlich ist, müssen die Schieberegister mit einem wesentlich langsameren Soft-SPI angesprochen werden. Der USB-Client reagiert bei dem Beginn einer Übertragung mit einem Aufruf der Methode usbFunctionSetup. In ihr wird dann entschieden, ob es sich um einen Schreib- oder Lesevorgang handelt. Hier wird zum einen die Speicheradresse auf 0 gesetzt und beim Leseaufruf die Zustände der Registereingänge in den RAM geschrieben. Anschließend wird von V-USB usbFunctionWrite bzw. usbFunctionRead je nach Reportgröße mehrmals aufgerufen. Im Read wird einfach nur der Inhalt des RAMs an den PC übertragen, beim Schreiben wird zuerst die Variable (die gleiche wie beim Lesen) gefüllt und nach dem letzten Wert vom PC die Methode processCommand aufgerufen. Die übertragenen Werte werden in Anschlussreihenfolge aus Sicht der Hauptplatine angegeben. Gibt man z.B. 0x01 0x02 aus, wird am Ausgabemodul, das am nächsten zur Hauptplatine angeschlossen ist 0x01 ausgegeben, am "zweitnächsten" 0x02. Bei den Eingabemodulen verhält es sich genauso. Dort findet das eigentliche Schreiben auf die Register statt. Zusätzlich zum simplen Schreiben kann man den Controller mit ein paar Logikfunktionen beauftragen. Diese werden immer mit der letzten Ausgabe verarbeitet. Folgende Operationen sind möglich: * Überschreiben * OR * AND * XOR Zusätzlich kann man ein Flag zum Invertieren übergeben, dadurch werden die Funktionen NOR, NAND und XNOR sowie invertiertes Überschreiben ermöglicht. Mit einem weiteren Flag kann man die errechneten Werte ins EEProm des Controllers schreiben. Dadurch kann man direkt beim Einschalten der Hardware einen definierten Zustand ausgeben. Das einzige, das man in der Software noch anpassen muss, ist die Anzahl der jeweiligen Schieberegister. Oder einfach unverändert lassen - dann werden jeweils 8 Register angenommen. Diese Werte muss man nur anpassen, wenn man mehr als 8 Schieberegister verwendet oder mehr Performance (Auswirkung noch nicht geprüft) wünscht. Ferner kann man eine ID in den EEProm schreiben, um mehrere (256) Devices zu unterscheiden. Diese ID wird bei jedem Lese-Vorgang im untersten Byte des Reports zurückgegeben. [[Bild:Usblotio_fuses.png|thumb|Im AVR programmierte Fuses]] Damit man die Hardware vollständig genutzt werden kann, müssen die Fuses wie folgt programmiert werden (siehe auch Screenshot): * Extended: 0xFF * High: 0x75 * Low: 0xE1 SPIEN kann nur deaktiviert werden, wenn man per HVSP programmiert, RSTDISBL ''sollte'' eigentlich reichen, habe ich allerdings nicht ausprobiert ;-) === PC === Auf dem PC kann eigentlich alles werkeln, was auf die entsprechenden USB-APIs zugreifen kann. Ich beschränke mich auf Windows, die Portierung auf *nix/Mac/etc. sollte aber nicht allzu schwierig sein. Im Grunde muss man nicht viel machen, das Schwierigste dürfte wahrscheinlich das Finden des Devices sein. Ich habe im C#-Programm Teile aus der [http://www.brianpeek.com/blog/pages/wiimotelib.aspx WiimoteLib] von Brian Peek genommen. Ist das HID gefunden und ein Handler gesetzt, können mit HidD_SetFeature und -GetFeature Reports an den AVR gesendet oder von ihm angefordert werden. Wichtig ist hier eigentlich nur die Größe des übergebenen Arrays, bei falscher Länge kommt oft einfach nichts beim Device an! Man kann relativ viel Zeit damit verbringen, dort nach einem Fehler zu suchen, zumal sich ein vollbelegter Mikrocontroller (dessen UART man nicht verwenden kann) schlecht debuggen lässt. Zur Demonstration habe ich eine kleine Konsolen-Anwendung rund um die USBLotIO-Klasse geschrieben. Kann sein, dass ich die Klasse noch ein wenig umstrukturiere - die nullable Byte-Arrays gefallen mir nicht sonderlich. Im Ordner \csharp\USBlotIO\bin\Release\ befindet sich ein kleines Konsolenprogramm (USBlotIO.exe), mit dem man alle Features der Hardware testen/nutzen kann. Einfach einmal ohne Parameter starten, dann werden alle möglichen Aufrufe angezeigt (wem es beim Start per Doppelklick zu schnell geht: cmd starten und damit die Anwendung aufrufen). == Test == Die Hardwareinstallation ist im Baukastenprinzip. Module anstecken und per USB-Kabel mit dem PC verbinden. Nach wenigen Sekunden ist das Gerät bereit für die Verwendung. Leider konnte ich das Board für Eingabemodule nicht testen, da Reichelt keine 74xx165 in SMD hat. Auf dem Breadboard hat es funktioniert, dennoch gebe ich momentan keine 100%ige Garantie auf korrekte Funktion! Erfolgreich getestet wurde die C#-Anwendung bisher unter WinXP Pro SP3 sowie Windows 7. Für Vista brauche ich erst noch einen Probanden, Windows 2000 lasse ich außen vor (freue mich aber über Erfolgsmeldungen). == Download == [[Datei:Usblotio.zip]] Firmware, EAGLE-Dateien und C#-Testprogramm (VS2008, .NET 2.0) [[Category:AVR]] [[Category:USB]] [[Category:PC]] 8d9748904a1eddbc1b5dfc017a186003e1f3fdfc Datei:Usblotio.zip 6 96 346 2009-12-26T22:15:43Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 353 346 2009-12-27T22:27:57Z Chris 2 hat eine neue Version von „[[Datei:Usblotio.zip]]“ hochgeladen:&#32;kleine Fehler korrigiert, unnötige Dateien gelöscht, ELF-Datei nochmal korrekt generiert wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Usblotio main.jpg 6 97 348 2009-12-26T23:24:20Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Hauptseite 0 1 351 338 2009-12-26T23:41:55Z Chris 2 News aktualisiert wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. ==Neues== 27.12.2009 [[USBLotIO]] 04.07.2009 [[Touchlight]] 19.01.2009 [[Datenlogger]] 01.09.2008 [[Labornetzteil]] 09.08.2008 [[Cursor]] 8cbfa45cfc69ee62e60ec524fd8690f10d181dfc 375 351 2010-02-12T21:32:33Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. ==Neues== 12.02.2010 [[Panasonic-Zapper]] 27.12.2009 [[USBLotIO]] 04.07.2009 [[Touchlight]] 19.01.2009 [[Datenlogger]] 01.09.2008 [[Labornetzteil]] dcca2b9dff91f593ce1480b29fc724bc12b336b1 383 375 2010-02-24T17:03:57Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. ==Neues== 24.02.2010 [[UnitColor]] 12.02.2010 [[Panasonic-Zapper]] 27.12.2009 [[USBLotIO]] 04.07.2009 [[Touchlight]] 19.01.2009 [[Datenlogger]] 4781d8812094570201018084228bafaf2e3c1098 Datei:Usblotio fuses.png 6 98 352 2009-12-27T22:27:01Z Chris 2 Fuses für den AVR wikitext text/x-wiki Fuses für den AVR d5bd523fafdf103ef27bbb1c2aad027bea92b1e6 Datei:Usblotio out.jpg 6 99 355 2009-12-27T22:45:56Z Chris 2 Ausgabemodul wikitext text/x-wiki Ausgabemodul 4f03a170b19ff97e03c56903310ec556d02932ed Hobbyelektronik.org:�ber Hobbyelektronik.org 4 100 357 2010-01-02T19:10:00Z Chris 2 Die Seite wurde neu angelegt: „Hobbyelektronik.org ist eine private, nichtkommerzielle Homepage.<br>Die Inhalte auf dieser Homepage entstehen in unserer Freizeit mit den uns zur Verfügung steh…“ wikitext text/x-wiki Hobbyelektronik.org ist eine private, nichtkommerzielle Homepage.<br>Die Inhalte auf dieser Homepage entstehen in unserer Freizeit mit den uns zur Verfügung stehenden Mitteln und haben "rein informellen" Charakter. = Haftungsausschluss<br> = == Inhalt<br> == Es ist nicht auszuschließen, dass hier vorgestellte Schaltungen, Texte oder Beschreibungen Fehler enthalten und ein Nachbau nicht funktioniert.<br>Weiterhin übernehmen wir keine Haftung für Schäden, die durch das Lesen dieser Homepage, den Nachbau von Schaltungen bzw. Anwendung der hier gezeigten Techniken und auch deren Folgen entstehen können.<br>Dies gilt insbesondere für Auf- oder Nachbauten, die mit Spannungen und Strömen im lebensgefährlichen Bereich liegen. '''Wenn du nicht genau weißt, was du machst, lass es lieber sein!<br>'''Warnhinweise sind nicht ohne Grund angebracht und müssen auf jeden Fall beachtet werden. Das Ganze gilt selbstverständlich auch für die Kommunikation (z. B. über E-Mail, IRC oder ICQ) mit uns. == Links == Für Internetseiten, die sich außerhalb der Domain hobbyelektronik.org befinden und hier verlinkt sind, könen wir trotz sorgfältiger Prüfung keinen Einfluss übernehmen.<br>Für die verlinkten Seiten sind die jeweiligen Webmaster/Autoren verantwortlich.<br>Solltest du auf dieser Homepage Verweise auf anstößige oder illegale Seiten finden, so nimm bitte so schnell wie möglich Kontakt mit uns auf, sodass wir die Verknüpfung entfernen können. <br> <br> ec054ec83b4123b0633aa75224cc8ed645b05b57 Datei:Pool ledatrix2.jpg 6 102 359 2010-01-10T14:20:54Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Benutzer:Chris 2 45 364 309 2010-01-26T22:14:09Z Chris 2 wikitext text/x-wiki Tjo, das ist es also, mein ganz privater Bereich auf hobbyelektronik.org. Ich bin Chris und quasi der Schöpfer von der Homepage hier. Irgendwann in diesem Jahrhundert (lt. Archive.org Ende 2003) fing ich damit an, meine mehr oder weniger gelungenen Bastel-Projekte auf hobby-elektronik.de.vu zu veröffentlichen. Damals noch bei Tripod. Der Speicherplatz wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich irgendwann, auf das schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10 April 2005 die Domain hobbyelektronik.org gekauft. Zu .org kam es, da mir eine Woche davor jemand die .net-Domain "geklaut" hat. Im Nachhinein bin ich glücklich um diesen Zustand - damit bin ich/sind wir dem .NET-Hype vollkommen entgangen. Eine richtige Organisation sind wir zwar noch immer nicht aber das kann ja noch werden ;) Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" (oder so ähnlich) schimpfen. Seit Oktober 2009 bin ich Student der Elektrotechnik/Nachrichtentechnik an der [http://www.hs-ulm.de Hochschule Ulm]. == Hobbies == * Elektronik ** Digitales (analoge Schaltungen sind mir irgendwie unheimlich *g*) ** Alles, das irgendwas anzeigt ** AVRs ** Sensoren ** Interfaces (v. a. zum PC) * Programmieren ** C# ** PHP ** JavaScript (mit allem Drum und Dran) ** C (für AVRs) 8134093619c532bc58de7997907e53e010a07839 Datei:Panasonic.wav 6 104 365 2010-02-09T23:42:51Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Panasonic brd.png 6 105 366 2010-02-12T21:17:15Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Panasonic sch.png 6 106 367 2010-02-12T21:17:59Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Panasonic real.jpg 6 107 368 2010-02-12T21:18:24Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Panasonic filter.png 6 108 369 2010-02-12T21:18:54Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Panasonic fb.png 6 109 370 2010-02-12T21:19:12Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 384 370 2010-02-28T19:17:13Z Chris 2 hat eine neue Version von „[[Datei:Panasonic fb.png]]“ hochgeladen:&#32;mit [[UnitColor]] bearbeitet wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Panasonic stoerung.png 6 110 371 2010-02-12T21:19:27Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 385 371 2010-02-28T19:18:10Z Chris 2 hat eine neue Version von „[[Datei:Panasonic stoerung.png]]“ hochgeladen:&#32;mit [[Unitcolor]] bearbeitet wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:PanasonicOff.zip 6 111 372 2010-02-12T21:20:48Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Panasonic-Zapper 0 112 373 2010-02-12T21:31:09Z Chris 2 Die Seite wurde neu angelegt: „Mein Vater hat, wie viele, die Angewohnheit, vor dem Fernseher einzuschlafen. Soweit nicht schlimm, allerdings geht es auf Dauer unnötigerweise auf die Stromrech…“ wikitext text/x-wiki Mein Vater hat, wie viele, die Angewohnheit, vor dem Fernseher einzuschlafen. Soweit nicht schlimm, allerdings geht es auf Dauer unnötigerweise auf die Stromrechnung und die Flimmerkiste wird dadurch auch nicht jünger. Manchmal kommt noch jemand am Wohnzimmer vorbei und schaltet das Gerät ab. Das muss doch auch einfacher gehen... ==Ideen== Meine erste Idee war, dem Teil per Zeitschaltuhr zumindest für eine Minute pro Nacht den Saft abzudrehen. Anders als unser alter Telefunken geht der Panasonic nach Spannungsrückkehr _nicht_ in den Stand-By. Genauso ist ihm die 12V-Steuerspannung am Scart grundsätzlich egal, sodass man selbes Spiel mit dem SAT-Receiver treiben könnte. Die zweite Idee war (auch noch vor dem Erlangen von Kenntnissen in der µC-Programmierung) war, eine Universal-Fernbedienung mit einem Wecker zu verheiraten. Blöd nur: Der Wecker schaltet seinen Alarmkontakt für einige Minuten, die Fernbedienung wird also unnötig lange betätigt, die Batterien gehen schnell leer und man hat eine Aperatur, die zwei Mal am Tag die Glotze abdreht und gleichzeitig die Fernbedienung zum wiederanschalten in dieser Zeit blockiert. Das hat weder [http://de.wikipedia.org/wiki/Woman_acceptance_factor WAF] noch <span title="father acceptance factor">FAF</span>. Das mit der Universal-Fernbedienung habe ich daher auch relativ schnell verworfen, die Idee mit dem Wecker blieb noch eine Weile. ==Die Lösung== Der nächste Ansatz war, die Fernbedienung in einem Mikrocontroller nachzubilden. Seit dem [http://ladyada.net/make/tvbgone/ TV-B-Gone] ist das massenhafte Abschalten von TV-Geräten ein Geek-Volkssport geworden. Ein guter Ansatz. Als nächstes schaute ich mir die [http://lirc.sourceforge.net/remotes/ Fernbedienungs-Bibliothek von LIRC] an. Von Panasonic gibt es genügend Codes. Allerdings keinen, der (auf den ersten Blick) exakt auf die Fernbedienung hier passt. Also: Fototranse an die Soundkarte anklemmen, aufnehmen ([[Datei:Panasonic.wav]]) und genauer anschauen (z. B. mit [http://audacity.sourceforge.net/ Audacity]). Netterweise war die Soundkarte lahm und übersteuert genug, dass man keinen 38kHz-Filter auf die Aufnahme anwenden musste (an den Flanken sieht man noch ein bisschen was). Mit Papier und Bleistift habe ich dann das Protokoll analysiert und vollständige Übereinstimmung zu einer Definition von LIRC gefunden. Muss das Signal nur noch nachgebaut werden. Die Ausgabe der Bytes ist kein Problem, nur das Trägersignal von 38kHz macht mir etwas Sorgen. Zwar kann man dies auch mit C halbwegs gut zu Fuß ausgeben, muss aber beim Timing etwas aufpassen. Netterweise kann man selbst mit dem sonst recht schwachen ATtiny13 hardwareseitig Signale mit einem Rechteck moduliert ausgeben. Spart man sich einen NE555 bzw. nervige Timinganpassungen. Den Code hierfür habe ich auch beim TV-B-Gone wiederentdeckt. Nachdem der Fernbedienungscode dem Mikrocontroller beigebracht und das Timing noch ein bisschen angepasst wurde (kommt auf 99% an das Original heran), ging die Überlegerei wieder los: wie auslösen? Hier kommt der Wecker wieder ins Spiel: Statt meinen Vater zu wecken (damit er den Fernseher abstellt), kann der doch die Stromversorgung schalten. Blöd auch hier wieder: Zwei Spannungsquellen, weil der AVR halbwegs genau 5V sehen will, da sonst der RC-Taktgeber einen zu niedrigen Takt ausgibt und von der IR-LED nur noch Kauderwelsch kommt. Außerdem sind Wecker unerhört teuer - da lohnt es sich schon fast, eine RTC samt Display an den kleinen anzuschließen. Totaler Overkill ==Die bessere Lösung== Irgendwann fiel es mir wie Schuppen von den Augen: Das deutlichste Indiz für die (Nicht-)Benutzung des Fernsehers ist die Bedienung! Es reicht zu beobachten, ob der Verseher aktiv genutzt wird, sprich: ob man den Sender wechselt, die Lautstärke verändert oder einfach nur wahllos auf der Fernbedienung herumdrückt. Ein IR-Empfänger mit Tageslicht- und 38kHz-Filter liegt noch herum, also anschließen und gucken, was passiert. Der Einfachheit halber hängt das Teil am Interrupt-Eingang des AVR. Beim auslösen wird ein Zähler gesetzt und per Timer langsam heruntergezählt. Damit die Glotze nicht an der spannensten Stelle eines längeren Films einfach ausgeht, blinkt in den letzten 15 Minuten eine LED. Diese wird auch beim Auslösen des Interrupts des IR-Empfängers kurz aktiviert. Beim Herumspielen mit der Schaltung habe ich jedoch eine Feststellung gemacht: ab und zu reagiert der Empfänger auch auf andere Lichteinflüsse (oder er hat einfach nur einen Knall) und gibt einen kurzen Impuls ab. Der Puls reicht aus, um den Timer wieder zurückzusetzen, also sehr ungeschickt. ===Filter=== Ein Filter muss her. Da ich keine größere Lust hatte und gleichzeitig mit meinem DSO spielen wollte, wurde er heuristisch aufgebaut. Mehr oder weniger wahllos Bauteile gesetzt, bis das herauskam, was ich wollte. [[Bild:Panasonic_filter.png]] Kurz zur Funktionsweise: R1 zieht den Ausgang OpenCollector-Ausgang des IR-Empfängers auf 5V, gleiches macht R3 mit dem Elko. Hat der Empfänger ein Signal erkannt, zieht er seinen Ausgang auf Low und dadurch die Spannung am Elko auf etwa 0,7V (bedingt durch die Diode). Die Diode bewirkt, dass der Kondensator nur durch den 10k-Widerstand (und nicht auch durch R1 und R2) geladen wird. R2 kann man bei entsprechender Wahl von R1 auch weglassen - nachdem es so aber recht gut klappte: never change a running system ;) <gallery> Bild:Panasonic_fb.png|Gefiltertes Signal einer Fernbedienung Bild:Panasonic_stoerung.png|Störung am Empfänger </gallery> CH1 (cyan) ist jeweils das "gefilterte" Ausgangssignal, CH2 (gelb) das, was vom Empfänger kommt. Die blauen Linien sind stehen für die Spannung, ab der der AVR eine Eingangsspannung als Low-Pegel erkennt. Beim Empfang einer Fernbedienung sieht man, dass die Spannung zuverlässig unterschritten wird. Im rechten Bild wurde mit einem Laserpointer mit hohem IR-Anteil das Auslösen provoziert beim ersten Schalten des Empfängers wäre der Timer bereits zurückgesetzt worden, durch die Entladekurve, bleibt die Spannung allerdings noch über dem Ansprechwert. Bei der zweiten Störung, die ich empfangen habe, löste die Schaltung gerade so nach knapp 9ms aus. Allerdings ist auch der Spannungspegel vor der erneuten Störung zu beachten: durch die vorhergehende Spitze wurde der Kondensator schon ein Stück entladen, eine Auslösung fällt bei nachfolgenden Signalen also leichter. ==Schaltung== So schauts aus: <gallery> Bild:Panasonic_sch.png|Stromlaufplan Bild:Panasonic_brd.png|Board (optimiert für Lochraster) Bild:Panasonic_real.jpg|Aufbau in Natura </gallery> ==Download== [[Datei:PanasonicOff.zip]] C-Code und EAGLE-Dateien 9b33f6ff7dada0563034782cf96e42f0d45a2034 374 373 2010-02-12T21:31:58Z Chris 2 Warum merke ich erst immer nach dem Speichern, dass die Kategorie fehlt...? wikitext text/x-wiki Mein Vater hat, wie viele, die Angewohnheit, vor dem Fernseher einzuschlafen. Soweit nicht schlimm, allerdings geht es auf Dauer unnötigerweise auf die Stromrechnung und die Flimmerkiste wird dadurch auch nicht jünger. Manchmal kommt noch jemand am Wohnzimmer vorbei und schaltet das Gerät ab. Das muss doch auch einfacher gehen... ==Ideen== Meine erste Idee war, dem Teil per Zeitschaltuhr zumindest für eine Minute pro Nacht den Saft abzudrehen. Anders als unser alter Telefunken geht der Panasonic nach Spannungsrückkehr _nicht_ in den Stand-By. Genauso ist ihm die 12V-Steuerspannung am Scart grundsätzlich egal, sodass man selbes Spiel mit dem SAT-Receiver treiben könnte. Die zweite Idee war (auch noch vor dem Erlangen von Kenntnissen in der µC-Programmierung) war, eine Universal-Fernbedienung mit einem Wecker zu verheiraten. Blöd nur: Der Wecker schaltet seinen Alarmkontakt für einige Minuten, die Fernbedienung wird also unnötig lange betätigt, die Batterien gehen schnell leer und man hat eine Aperatur, die zwei Mal am Tag die Glotze abdreht und gleichzeitig die Fernbedienung zum wiederanschalten in dieser Zeit blockiert. Das hat weder [http://de.wikipedia.org/wiki/Woman_acceptance_factor WAF] noch <span title="father acceptance factor">FAF</span>. Das mit der Universal-Fernbedienung habe ich daher auch relativ schnell verworfen, die Idee mit dem Wecker blieb noch eine Weile. ==Die Lösung== Der nächste Ansatz war, die Fernbedienung in einem Mikrocontroller nachzubilden. Seit dem [http://ladyada.net/make/tvbgone/ TV-B-Gone] ist das massenhafte Abschalten von TV-Geräten ein Geek-Volkssport geworden. Ein guter Ansatz. Als nächstes schaute ich mir die [http://lirc.sourceforge.net/remotes/ Fernbedienungs-Bibliothek von LIRC] an. Von Panasonic gibt es genügend Codes. Allerdings keinen, der (auf den ersten Blick) exakt auf die Fernbedienung hier passt. Also: Fototranse an die Soundkarte anklemmen, aufnehmen ([[Datei:Panasonic.wav]]) und genauer anschauen (z. B. mit [http://audacity.sourceforge.net/ Audacity]). Netterweise war die Soundkarte lahm und übersteuert genug, dass man keinen 38kHz-Filter auf die Aufnahme anwenden musste (an den Flanken sieht man noch ein bisschen was). Mit Papier und Bleistift habe ich dann das Protokoll analysiert und vollständige Übereinstimmung zu einer Definition von LIRC gefunden. Muss das Signal nur noch nachgebaut werden. Die Ausgabe der Bytes ist kein Problem, nur das Trägersignal von 38kHz macht mir etwas Sorgen. Zwar kann man dies auch mit C halbwegs gut zu Fuß ausgeben, muss aber beim Timing etwas aufpassen. Netterweise kann man selbst mit dem sonst recht schwachen ATtiny13 hardwareseitig Signale mit einem Rechteck moduliert ausgeben. Spart man sich einen NE555 bzw. nervige Timinganpassungen. Den Code hierfür habe ich auch beim TV-B-Gone wiederentdeckt. Nachdem der Fernbedienungscode dem Mikrocontroller beigebracht und das Timing noch ein bisschen angepasst wurde (kommt auf 99% an das Original heran), ging die Überlegerei wieder los: wie auslösen? Hier kommt der Wecker wieder ins Spiel: Statt meinen Vater zu wecken (damit er den Fernseher abstellt), kann der doch die Stromversorgung schalten. Blöd auch hier wieder: Zwei Spannungsquellen, weil der AVR halbwegs genau 5V sehen will, da sonst der RC-Taktgeber einen zu niedrigen Takt ausgibt und von der IR-LED nur noch Kauderwelsch kommt. Außerdem sind Wecker unerhört teuer - da lohnt es sich schon fast, eine RTC samt Display an den kleinen anzuschließen. Totaler Overkill ==Die bessere Lösung== Irgendwann fiel es mir wie Schuppen von den Augen: Das deutlichste Indiz für die (Nicht-)Benutzung des Fernsehers ist die Bedienung! Es reicht zu beobachten, ob der Verseher aktiv genutzt wird, sprich: ob man den Sender wechselt, die Lautstärke verändert oder einfach nur wahllos auf der Fernbedienung herumdrückt. Ein IR-Empfänger mit Tageslicht- und 38kHz-Filter liegt noch herum, also anschließen und gucken, was passiert. Der Einfachheit halber hängt das Teil am Interrupt-Eingang des AVR. Beim auslösen wird ein Zähler gesetzt und per Timer langsam heruntergezählt. Damit die Glotze nicht an der spannensten Stelle eines längeren Films einfach ausgeht, blinkt in den letzten 15 Minuten eine LED. Diese wird auch beim Auslösen des Interrupts des IR-Empfängers kurz aktiviert. Beim Herumspielen mit der Schaltung habe ich jedoch eine Feststellung gemacht: ab und zu reagiert der Empfänger auch auf andere Lichteinflüsse (oder er hat einfach nur einen Knall) und gibt einen kurzen Impuls ab. Der Puls reicht aus, um den Timer wieder zurückzusetzen, also sehr ungeschickt. ===Filter=== Ein Filter muss her. Da ich keine größere Lust hatte und gleichzeitig mit meinem DSO spielen wollte, wurde er heuristisch aufgebaut. Mehr oder weniger wahllos Bauteile gesetzt, bis das herauskam, was ich wollte. [[Bild:Panasonic_filter.png]] Kurz zur Funktionsweise: R1 zieht den Ausgang OpenCollector-Ausgang des IR-Empfängers auf 5V, gleiches macht R3 mit dem Elko. Hat der Empfänger ein Signal erkannt, zieht er seinen Ausgang auf Low und dadurch die Spannung am Elko auf etwa 0,7V (bedingt durch die Diode). Die Diode bewirkt, dass der Kondensator nur durch den 10k-Widerstand (und nicht auch durch R1 und R2) geladen wird. R2 kann man bei entsprechender Wahl von R1 auch weglassen - nachdem es so aber recht gut klappte: never change a running system ;) <gallery> Bild:Panasonic_fb.png|Gefiltertes Signal einer Fernbedienung Bild:Panasonic_stoerung.png|Störung am Empfänger </gallery> CH1 (cyan) ist jeweils das "gefilterte" Ausgangssignal, CH2 (gelb) das, was vom Empfänger kommt. Die blauen Linien sind stehen für die Spannung, ab der der AVR eine Eingangsspannung als Low-Pegel erkennt. Beim Empfang einer Fernbedienung sieht man, dass die Spannung zuverlässig unterschritten wird. Im rechten Bild wurde mit einem Laserpointer mit hohem IR-Anteil das Auslösen provoziert beim ersten Schalten des Empfängers wäre der Timer bereits zurückgesetzt worden, durch die Entladekurve, bleibt die Spannung allerdings noch über dem Ansprechwert. Bei der zweiten Störung, die ich empfangen habe, löste die Schaltung gerade so nach knapp 9ms aus. Allerdings ist auch der Spannungspegel vor der erneuten Störung zu beachten: durch die vorhergehende Spitze wurde der Kondensator schon ein Stück entladen, eine Auslösung fällt bei nachfolgenden Signalen also leichter. ==Schaltung== So schauts aus: <gallery> Bild:Panasonic_sch.png|Stromlaufplan Bild:Panasonic_brd.png|Board (optimiert für Lochraster) Bild:Panasonic_real.jpg|Aufbau in Natura </gallery> ==Download== [[Datei:PanasonicOff.zip]] C-Code und EAGLE-Dateien [[Category:AVR]] 6e6b242b9b26e821f3128996b97694141b0a601c 377 374 2010-02-13T10:38:18Z Chris 2 Screenshot der Fuses im ATtiny hinzugefügt wikitext text/x-wiki Mein Vater hat, wie viele, die Angewohnheit, vor dem Fernseher einzuschlafen. Soweit nicht schlimm, allerdings geht es auf Dauer unnötigerweise auf die Stromrechnung und die Flimmerkiste wird dadurch auch nicht jünger. Manchmal kommt noch jemand am Wohnzimmer vorbei und schaltet das Gerät ab. Das muss doch auch einfacher gehen... ==Ideen== Meine erste Idee war, dem Teil per Zeitschaltuhr zumindest für eine Minute pro Nacht den Saft abzudrehen. Anders als unser alter Telefunken geht der Panasonic nach Spannungsrückkehr _nicht_ in den Stand-By. Genauso ist ihm die 12V-Steuerspannung am Scart grundsätzlich egal, sodass man selbes Spiel mit dem SAT-Receiver treiben könnte. Die zweite Idee war (auch noch vor dem Erlangen von Kenntnissen in der µC-Programmierung) war, eine Universal-Fernbedienung mit einem Wecker zu verheiraten. Blöd nur: Der Wecker schaltet seinen Alarmkontakt für einige Minuten, die Fernbedienung wird also unnötig lange betätigt, die Batterien gehen schnell leer und man hat eine Aperatur, die zwei Mal am Tag die Glotze abdreht und gleichzeitig die Fernbedienung zum wiederanschalten in dieser Zeit blockiert. Das hat weder [http://de.wikipedia.org/wiki/Woman_acceptance_factor WAF] noch <span title="father acceptance factor">FAF</span>. Das mit der Universal-Fernbedienung habe ich daher auch relativ schnell verworfen, die Idee mit dem Wecker blieb noch eine Weile. ==Die Lösung== Der nächste Ansatz war, die Fernbedienung in einem Mikrocontroller nachzubilden. Seit dem [http://ladyada.net/make/tvbgone/ TV-B-Gone] ist das massenhafte Abschalten von TV-Geräten ein Geek-Volkssport geworden. Ein guter Ansatz. Als nächstes schaute ich mir die [http://lirc.sourceforge.net/remotes/ Fernbedienungs-Bibliothek von LIRC] an. Von Panasonic gibt es genügend Codes. Allerdings keinen, der (auf den ersten Blick) exakt auf die Fernbedienung hier passt. Also: Fototranse an die Soundkarte anklemmen, aufnehmen ([[Datei:Panasonic.wav]]) und genauer anschauen (z. B. mit [http://audacity.sourceforge.net/ Audacity]). Netterweise war die Soundkarte lahm und übersteuert genug, dass man keinen 38kHz-Filter auf die Aufnahme anwenden musste (an den Flanken sieht man noch ein bisschen was). Mit Papier und Bleistift habe ich dann das Protokoll analysiert und vollständige Übereinstimmung zu einer Definition von LIRC gefunden. Muss das Signal nur noch nachgebaut werden. Die Ausgabe der Bytes ist kein Problem, nur das Trägersignal von 38kHz macht mir etwas Sorgen. Zwar kann man dies auch mit C halbwegs gut zu Fuß ausgeben, muss aber beim Timing etwas aufpassen. Netterweise kann man selbst mit dem sonst recht schwachen ATtiny13 hardwareseitig Signale mit einem Rechteck moduliert ausgeben. Spart man sich einen NE555 bzw. nervige Timinganpassungen. Den Code hierfür habe ich auch beim TV-B-Gone wiederentdeckt. Nachdem der Fernbedienungscode dem Mikrocontroller beigebracht und das Timing noch ein bisschen angepasst wurde (kommt auf 99% an das Original heran), ging die Überlegerei wieder los: wie auslösen? Hier kommt der Wecker wieder ins Spiel: Statt meinen Vater zu wecken (damit er den Fernseher abstellt), kann der doch die Stromversorgung schalten. Blöd auch hier wieder: Zwei Spannungsquellen, weil der AVR halbwegs genau 5V sehen will, da sonst der RC-Taktgeber einen zu niedrigen Takt ausgibt und von der IR-LED nur noch Kauderwelsch kommt. Außerdem sind Wecker unerhört teuer - da lohnt es sich schon fast, eine RTC samt Display an den kleinen anzuschließen. Totaler Overkill ==Die bessere Lösung== Irgendwann fiel es mir wie Schuppen von den Augen: Das deutlichste Indiz für die (Nicht-)Benutzung des Fernsehers ist die Bedienung! Es reicht zu beobachten, ob der Verseher aktiv genutzt wird, sprich: ob man den Sender wechselt, die Lautstärke verändert oder einfach nur wahllos auf der Fernbedienung herumdrückt. Ein IR-Empfänger mit Tageslicht- und 38kHz-Filter liegt noch herum, also anschließen und gucken, was passiert. Der Einfachheit halber hängt das Teil am Interrupt-Eingang des AVR. Beim auslösen wird ein Zähler gesetzt und per Timer langsam heruntergezählt. Damit die Glotze nicht an der spannensten Stelle eines längeren Films einfach ausgeht, blinkt in den letzten 15 Minuten eine LED. Diese wird auch beim Auslösen des Interrupts des IR-Empfängers kurz aktiviert. Beim Herumspielen mit der Schaltung habe ich jedoch eine Feststellung gemacht: ab und zu reagiert der Empfänger auch auf andere Lichteinflüsse (oder er hat einfach nur einen Knall) und gibt einen kurzen Impuls ab. Der Puls reicht aus, um den Timer wieder zurückzusetzen, also sehr ungeschickt. ===Filter=== Ein Filter muss her. Da ich keine größere Lust hatte und gleichzeitig mit meinem DSO spielen wollte, wurde er heuristisch aufgebaut. Mehr oder weniger wahllos Bauteile gesetzt, bis das herauskam, was ich wollte. [[Bild:Panasonic_filter.png]] Kurz zur Funktionsweise: R1 zieht den Ausgang OpenCollector-Ausgang des IR-Empfängers auf 5V, gleiches macht R3 mit dem Elko. Hat der Empfänger ein Signal erkannt, zieht er seinen Ausgang auf Low und dadurch die Spannung am Elko auf etwa 0,7V (bedingt durch die Diode). Die Diode bewirkt, dass der Kondensator nur durch den 10k-Widerstand (und nicht auch durch R1 und R2) geladen wird. R2 kann man bei entsprechender Wahl von R1 auch weglassen - nachdem es so aber recht gut klappte: never change a running system ;) <gallery> Bild:Panasonic_fb.png|Gefiltertes Signal einer Fernbedienung Bild:Panasonic_stoerung.png|Störung am Empfänger </gallery> CH1 (cyan) ist jeweils das "gefilterte" Ausgangssignal, CH2 (gelb) das, was vom Empfänger kommt. Die blauen Linien sind stehen für die Spannung, ab der der AVR eine Eingangsspannung als Low-Pegel erkennt. Beim Empfang einer Fernbedienung sieht man, dass die Spannung zuverlässig unterschritten wird. Im rechten Bild wurde mit einem Laserpointer mit hohem IR-Anteil das Auslösen provoziert beim ersten Schalten des Empfängers wäre der Timer bereits zurückgesetzt worden, durch die Entladekurve, bleibt die Spannung allerdings noch über dem Ansprechwert. Bei der zweiten Störung, die ich empfangen habe, löste die Schaltung gerade so nach knapp 9ms aus. Allerdings ist auch der Spannungspegel vor der erneuten Störung zu beachten: durch die vorhergehende Spitze wurde der Kondensator schon ein Stück entladen, eine Auslösung fällt bei nachfolgenden Signalen also leichter. ==Schaltung== So schauts aus: <gallery> Bild:Panasonic_sch.png|Stromlaufplan Bild:Panasonic_brd.png|Board (optimiert für Lochraster) Bild:Panasonic_real.jpg|Aufbau in Natura Bild:Panasonic_fuses.png|Fuses im ATtiny13 (H:0xF9, L:0x7A) </gallery> ==Download== [[Datei:PanasonicOff.zip]] C-Code und EAGLE-Dateien [[Category:AVR]] 56d27e7fe207a296fa642b9261deb34f6b82818a Datei:Panasonic fuses.png 6 113 376 2010-02-13T10:37:11Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Unit shot before.png 6 114 378 2010-02-24T16:13:42Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Unit shot after.png 6 115 379 2010-02-24T16:38:36Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:UnitColor 1.0.zip 6 116 380 2010-02-24T16:45:30Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 UnitColor 0 117 381 2010-02-24T16:50:03Z Chris 2 Erste Version veröffentlicht (diesmal sogar mit Kategorie ;)) wikitext text/x-wiki = Ausgangssituation = Seit kurzem bin [[Benutzer:Chris|ich]] stolzer Besitzer eines Uni-Trend Speicheroszilloskops. Das Teil macht hinsichtlich des Preises richtig viel Spaß, eines ist jedoch richtig blöd: Speichert man einen Screenshot auf einen kompatiblen* USB-Stick, stimmt die Farbpalette überhaupt nicht: [[Bild:Unit shot before.png]] Klar kann man die Farben manuell korrigieren, allerdings wird es nach dem 10 mal Wiederholen dieser Prozedur langweilig bis nervig. Das kann Software doch viel besser ;-) = Erster Versuch = Für schnelle Hacks nehme ich ganz gerne PHP - aus dem "schnellen Hack" wurde hier leider ein ziemlich ekelhaftes Stück Software, denn: * PHP kann native keine Windows-Bitmaps ([http://www.php.net/manual/en/function.imagecreatefromwbmp.php imagecreatefromwbmp] ist irreführend!) lesen * Man kann die Bild-Palette anscheinend nicht direkt manipulieren * Die Pixelfunktionen sind umständlich und langsam (warum verwenden sie ein Array statt dem überall üblichen Integer?) * Welcher "normale" Elektronik-Bastler hat PHP lokal installiert? Alles in Allem ziemlich großer Mist. (Wer will, kann sich die Quellen im Zip-Archiv ansehen) Deshalb: = Zweiter Versuch = Mit Bildverarbeitung habe ich C# zwar noch nicht sonderlich viel gemacht, aber einen Versuch ist es Wert. Das Schöne ist: Hier kann man die Bildpalette bearbeiten, was einen deutlichen Geschwindigkeitsvorteil verspricht. Man muss also nur die Farben ändern und die Datei als PNG abspeichern. Um die Farbänderungen zu erhalten, muss die Bildressource komischerweise in eine neue gezeichnet werden. Bei dieser Gelegenheit wird das unwichtige (da immer gleiche) Menü rechts abgeschnitten. Da (zumindest bei mir) die meisten aufgenommenen Bilder im Web landen, wäre es schön, wenn diese so klein wie möglich wären. Deshalb werden sie, sofern [http://optipng.sourceforge.net/ optipng.exe] vorhanden ist, mit derselben komprimiert. Im Schnitt wird aus den 80KiB großen Bitmaps 2KiB schlanke PNGs: [[Bild:Unit_shot_after.png]] == Bedienung == Wer nicht weiß, was er mit den Dateien im Zip-Archiv anfangen soll: Die wichtigen Dateien liegen im Ordner \c-sharp\bin\Release\! Die Bedienung gestaltet sich als sichtlich einfach. Man muss nur die UnitColor.exe mit den umzuwandelnden Bitmaps öffnen. Im einfachsten Fall können die Bilder einfach per Drag & Drop auf die Exe-Datei gezogen werden; die umgewandelten Dateien werden im gleichen Ordner wie die Quelldateien mit der Dateierweiterung .png gespeichert. = Download = [[Datei:UnitColor 1.0.zip]] Version 1.0 vom 24.02.2010 [[Kategory:Software]] 4023475ad146de7fac7d237bbe09e4ebc120c7bb 382 381 2010-02-24T17:03:30Z Chris 2 wikitext text/x-wiki = Ausgangssituation = Seit kurzem bin [[Benutzer:Chris|ich]] stolzer Besitzer eines Uni-Trend Speicheroszilloskops. Das Teil macht hinsichtlich des Preises richtig viel Spaß, eines ist jedoch richtig blöd: Speichert man einen Screenshot auf einen kompatiblen* USB-Stick, stimmt die Farbpalette überhaupt nicht: [[Bild:Unit shot before.png]] Klar kann man die Farben manuell korrigieren, allerdings wird es nach dem 10 mal Wiederholen dieser Prozedur langweilig bis nervig. Das kann Software doch viel besser ;-) = Erster Versuch = Für schnelle Hacks nehme ich ganz gerne PHP - aus dem "schnellen Hack" wurde hier leider ein ziemlich ekelhaftes Stück Software, denn: * PHP kann native keine Windows-Bitmaps ([http://www.php.net/manual/en/function.imagecreatefromwbmp.php imagecreatefromwbmp] ist irreführend!) lesen * Man kann die Bild-Palette anscheinend nicht direkt manipulieren * Die Pixelfunktionen sind umständlich und langsam (warum verwenden sie ein Array statt dem überall üblichen Integer?) * Welcher "normale" Elektronik-Bastler hat PHP lokal installiert? Alles in Allem ziemlich großer Mist. (Wer will, kann sich die Quellen im Zip-Archiv ansehen) Deshalb: = Zweiter Versuch = Mit Bildverarbeitung habe ich C# zwar noch nicht sonderlich viel gemacht, aber einen Versuch ist es Wert. Das Schöne ist: Hier kann man die Bildpalette bearbeiten, was einen deutlichen Geschwindigkeitsvorteil verspricht. Man muss also nur die Farben ändern und die Datei als PNG abspeichern. Um die Farbänderungen zu erhalten, muss die Bildressource komischerweise in eine neue gezeichnet werden. Bei dieser Gelegenheit wird das unwichtige (da immer gleiche) Menü rechts abgeschnitten. Da (zumindest bei mir) die meisten aufgenommenen Bilder im Web landen, wäre es schön, wenn diese so klein wie möglich wären. Deshalb werden sie, sofern [http://optipng.sourceforge.net/ optipng.exe] vorhanden ist, mit derselben komprimiert. Im Schnitt wird aus den 80KiB großen Bitmaps 2KiB schlanke PNGs: [[Bild:Unit_shot_after.png]] == Bedienung == Wer nicht weiß, was er mit den Dateien im Zip-Archiv anfangen soll: Die wichtigen Dateien liegen im Ordner \c-sharp\bin\Release\! Die Bedienung gestaltet sich als sichtlich einfach. Man muss nur die UnitColor.exe mit den umzuwandelnden Bitmaps öffnen. Im einfachsten Fall können die Bilder einfach per Drag & Drop auf die Exe-Datei gezogen werden; die umgewandelten Dateien werden im gleichen Ordner wie die Quelldateien mit der Dateierweiterung .png gespeichert. = Download = [[Datei:UnitColor 1.0.zip]] Version 1.0 vom 24.02.2010 [[Kategorie:Software]] 0847e47a87c2bb05c6d74ecefb08f5b42bb96c43 Datei:Usblotio sch.png 6 118 386 2010-02-28T19:24:32Z Chris 2 Stromlaufplan von USBLotIO wikitext text/x-wiki Stromlaufplan von USBLotIO cda31a8669187ba1d0606061e03ea446e0e8ed71 Datei:Resol sch.png 6 119 388 2010-03-04T16:08:31Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder 0 120 389 2010-03-04T17:03:29Z Chris 2 Die Seite wurde neu angelegt: „In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um ei…“ wikitext text/x-wiki In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem es keinerlei Informationen gibt. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die zwar Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). (to be continued...) af8e3dcd8a2cda53de402e3de6428956f7ce45f0 392 389 2010-03-04T19:52:53Z Chris 2 wikitext text/x-wiki In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem es keinerlei Informationen gibt. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die zwar Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <pre> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </pre> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <pre> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </pre> Der Debug in der Software schreibt einige Informationen zur Dekodierung auf einem LC-Display. Über UART macht das kaum Sinn, da man den Empfang der Daten verpasst. Zugegebermaßen: ich habe einen richtigen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: ==Debug-Ausgabe== Bei jedem Sync wird "Sync" angezeigt. Wurde der Head empfangen, kommt es zu folgender Ausgabe: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> C:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 S:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Bekannte Fehler/Macken== Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes: *Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt) *Sensorbruchsmaske ist 0 (4024) *Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht Folgendes wurde noch nicht getestet/ist unbekannt: *Negative Temperaturen *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Ziel der Daten (vbus_outdata) durch Pointer definierbar *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.1beta vom 04.03.2010 ATmega32 @ 12MHz An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen! =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie oben) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der der Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Maschinen]] 2499f03b893ad131e6ea52637e947f7424095faa 396 392 2010-03-04T22:30:11Z Chris 2 wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die zwar Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <pre> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </pre> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <pre> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </pre> Der Debug in der Software schreibt einige Informationen zur Dekodierung auf einem LC-Display. Über UART macht das kaum Sinn, da man den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Bei jedem Sync wird "Sync" angezeigt. Wurde der Head empfangen, kommt es zu folgender Ausgabe: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> C:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 S:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung und die des Resol ServiceCenters. Rot markiert: fehlerhafte Sätze]] Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes: *Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt) *Sensorbruchsmaske ist 0 (4024) *Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht *Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Ziel der Daten (vbus_outdata) durch Pointer definierbar *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.1beta vom 04.03.2010 ATmega32 @ 12MHz '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Maschinen]] dab8f8de1978e63adc8eee4086ccae015f55ea31 Datei:VBus-Protokollspezifikation.pdf 6 121 390 2010-03-04T18:46:57Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:VbusDecode.zip 6 122 391 2010-03-04T19:48:38Z Chris 2 Version 0.1beta vom 04.03.2010 wikitext text/x-wiki Version 0.1beta vom 04.03.2010 c28d770f302ad6299f601a13723df32b9e8ea6c4 Datei:Vbus debug.jpg 6 123 393 2010-03-04T22:07:19Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbus regler.jpg 6 124 394 2010-03-04T22:08:47Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbus putty vs rss.png 6 125 395 2010-03-04T22:22:45Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder 0 120 397 396 2010-03-04T22:35:04Z Chris 2 Debug wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die zwar Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <pre> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </pre> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <pre> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </pre> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> C:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 S:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung und die des Resol ServiceCenters. Rot markiert: fehlerhafte Sätze]] Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes: *Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt) *Sensorbruchsmaske ist 0 (4024) *Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht *Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Ziel der Daten (vbus_outdata) durch Pointer definierbar *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.1beta vom 04.03.2010 ATmega32 @ 12MHz '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Maschinen]] ccb98880df91a3ad14c102def118278018de8ac5 411 397 2010-03-09T19:41:37Z Chris 2 wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die zwar Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <pre> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </pre> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <pre> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </pre> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Maschinen]] 8b516515f96f730629922e938c3ec5f48fdec1cd Kategorie:AVR 14 126 398 2010-03-04T22:43:53Z Chris 2 Die Seite wurde neu angelegt: „Auf dieser Seite findest du alle Projekte, die entweder mit [http://atmel.com/products/avr/default.asp Atmels AVR]s zu tun haben oder mit einem dieser Mikrocontro…“ wikitext text/x-wiki Auf dieser Seite findest du alle Projekte, die entweder mit [http://atmel.com/products/avr/default.asp Atmels AVR]s zu tun haben oder mit einem dieser Mikrocontroller augebaut wurde. Wer sich mit der Programmierung von µCs beschäftigen möchte, dem sei [http://www.mikrocontroller.net/ Mikrocontroller.net] und dessen [http://www.mikrocontroller.net/articles/AVR-Tutorial Tutorial] zu [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial AVR-GCC] ans Herz gelegt. c65b9434bf0b38d104f078c8346f3e75b94b301b 399 398 2010-03-04T22:44:31Z Chris 2 Seitenkategorie angelegt (endlich mal) wikitext text/x-wiki Auf dieser Seite findest du alle Projekte, die entweder mit [http://atmel.com/products/avr/default.asp Atmels AVRs] zu tun haben oder mit einem dieser Mikrocontroller augebaut wurde. Wer sich mit der Programmierung von µCs beschäftigen möchte, dem sei [http://www.mikrocontroller.net/ Mikrocontroller.net] und dessen [http://www.mikrocontroller.net/articles/AVR-Tutorial Tutorial] zu [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial AVR-GCC] ans Herz gelegt. 4f89ad05a879d742f606a302b947a0882a1a92be PLL im ATTiny45 kalibrieren 0 40 400 56 2010-03-04T22:50:06Z Chris 2 überfälliger Hinweis zur Kalibrierung beim USB wikitext text/x-wiki Der ATTiny 45 besitzt neben dem Tiny 26 eine interne PLL, die es erlaubt, den Takt vom AVR während dem Betrieb zu verändern. Standardmäßig ist diese auf 16MHz eingestellt, allerdings kann man deren Takt durch Verändern des OSCCAL-Registers verändern. == Warum? == Bei manchen Anwendungen ist ein Takt abseits von 16MHz erforderlich, wie zum Beispiel bei AVR-USB. Hier muss die Frequenz 16.5MHz betragen, da das Device vom PC sonst nicht erkannt wird. == AVR-USB == <strike>Im Beispiel [http://www.obdev.at/products/avrusb/easylogger.html EasyLogger] wird die abweichende Frequenz in main() berechnet, falls kein abweichender Wert im EEProm steht. Allerdings funktioniert die Errechnung nicht immer zuverlässig. Dann muss man den Wert manuell ermitteln.</strike> '''Update:''' Mittlerweile ist es möglich, die PLL anhand der Framelänge vom USB zu kalibrieren. Es ist also nicht mehr nötig, den Takt manuell zu ermitteln. Ein Beispiel der Kalibrierung ist im Referenzprojekt [http://www.obdev.at/products/vusb/easylogger.html EasyLogger] von obdev. == Wert ermitteln == Man kann den OSCCAL-Wert natürlich per trial & error ermitteln, allerdings muss man (theoretisch) alle 256 Werte "durchprobieren". Wenn man vom festgelegten Registerwert ausgeht (lässt sich z. B. mit AVR Studio auslesen) kann man die Suche auf etwa 10-15 Werte beschränken. Allerdings ist das immernoch relativ Zeitaufwendig. Um die Sache zu erleichtern, bietet der ATTiny45 (wie eigentlich alle AVRs) die Funktion, den Takt auf einem Pin (PB4[?]) auszugeben. Dazu muss einfach die Fuse CKOUT aktiviert werden. Nun kann mit einem sehr simplen Programm und einem Frequenzzähler der CPU-Takt ermittelt werden: <pre> int main() { OSCCAL = 100; while(1); } </pre> Das Programm kann dann geflasht und der Takt an PB4 gemessen werden. Falls der Frequenzzähler (wie meiner) keine 16-20MHz mitmacht, kann die Fuse CKDIV8 (Takt durch 8 teilen) aktiviert werden. optional kann der Code auch dahingehend angepasst werden, dass er nicht mehrmals geflasht werden muss: <pre> int main() { DDRB &= ~(PB3) if(PINB | PB3) { OSCCAL = 150 } else { OSCCAL = 100; } while(1); } </pre> Wenn nun beim Anlegen der Spannung PB3 an Vcc anliegt, wird OSCCAL auf 150, andernfalls auf 100 gesetzt. Die Formel zum Berechnen des OSCCAL-Wertes lautet folgendermaßen: OSC<sub>ziel</sub> = (f<sub>max</sub>-f<sub>min</sub>)/(OSC<sub>max</sub>-OSC<sub>min</sub>)*(f<sub>ziel</sub>-OSC<sub>min</sub>)+f<sub>min</sub> Angenommen, bei OSCCAL 100 werden 15.5MHz gemessen und bei OSCCAL 150 eine Frequenz von 17.86MHz und die Zielfrequenz 16.5MHz beträgt, ergibt sich folgendes: OSC<sub>ziel</sub> = (17.86-15.5)/(150-100)*(16.5-100)+15.5 OSC<sub>ziel</sub> = 11.56 Der Wert für OSCCAL ist dann 12. Dieser Wert kann entweder an die erste Stelle im EEProm oder direkt ins Programm geschrieben werden. == Aber Vorsicht! == Beim Portieren von Schaltungen vom Steckbrett auf Lochraster/Platine kann es sein, dass man den AVR neu kalibrieren muss! Das führte beim [[SNES-Joypad]] ein bisschen zu Verwirrung, da die Schaltung auf dem Steckbrett aber auf der Platine nicht mehr vom PC erkannt wurde. Sobald ich wieder einen Tiny45 zum Basteln über habe, werde ich evtl. ein USB-Device bauen, das man direkt kalibrieren kann und der Wert direkt vom PC ausgelesen werden kann. [[Category:AVR]] [[Category:USB]] 2fcc62ca86e2d693d79cd07bed03e3662a419c79 Datei:Snes-usb sch.png 6 127 401 2010-03-04T22:59:24Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Snes-usb-2313 sch.png 6 128 402 2010-03-04T23:14:29Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Snes-usb-2313.zip 6 129 403 2010-03-04T23:15:34Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:SNES-USB-autocal.zip 6 130 404 2010-03-04T23:17:27Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 SNES-Joypad 0 35 405 343 2010-03-04T23:22:44Z Chris 2 wikitext text/x-wiki Als Kind hatte ich mir mal (ja, aus eigener Tasche) einen Super Nintendo gekauft. Nachdem er die Jahre leider nicht überlebt hat und ich doch ab und an mal ein bisschen Verlangen nach SNES habe, griff ich auf Emulatoren für den PC zurück. So gut die Programme auch sind - man hat ein Problem: man muss auf der Tastatur spielen. Das mag bei manchen Spielen noch gehen, wenn man jedoch in brenzliche Situationen kommt, braucht man dann doch die etwas trainierteren Daumen. Irgendwann kam ich auf die Idee, einfach das Gamepad an den PC anzuschließen. Mit einem Nachbau eines SNES-Gamepads, das ich mal geschenkt bekommen habe, funktionierte das ziemlich gut. Im Pad selbst waren zwei CD4021 (Schieberegister) verbaut. Die Funktionsweise des Gamepads ist somit genauso simpel wie... simpel. Wenn die CPU in der Konsole den Controller auslesen will, werden die Daten per Latch in das Register geladen, von wo es dann seriell ausgelesen werden kann. [[Bild:SNES-stecker.jpg|thumb|Anschlussbelegung am Stecker]] Die Beschaltung im Controller ist folgendermaßen: {| ! Pin|| Farbe || Funktion |- | 1 || braun || GND |- | 2 || rot || Data |- | 3 || orange || Latch |- | 4 || gelb || Clock |- | 5 || weiß || Vcc |} Bei meiner ersten Entwicklung war das Gamepad am Parallel-Port angeschlossen und wurde von einem kleinen VB-Programm ausgelesen. Die Tastenanschläge wurden dann per DLL als Tastatur-Eingaben simuliert. Das ganze hatte nur ein paar Nachteile: * Die Software war nicht besonders schön * Der Parallelport wurde (mal wieder) zweckentfremdet * Man muss hinter den PC kriechen, wenn man wieder etwas drucken will * Das Ganze ist einfach nicht rund (vorangegangene Punkte) * Mein Notebook hat weder eine parallele noch serielle Schnittstelle Irgendwann entdeckte ich [http://www.obdev.at/products/vusb/index-de.html V-USB], eine Software-Implementierung von USB in AVRs. Als Projekt war [http://www.raphnet.net/electronique/snes_nes_usb/index_en.php SNES/NES gamepad (and mouse) to USB adapter] verlinkt. Die Schaltung habe ich mir dann relativ zügig aufgebaut, um zu testen, ob da wirklich das dahintersteckt, was ich mir erwartet hatte. Tatsächlich meldete Windows 2s nach dem Einstecken der Konstruktion eine neue Hardware. Nur die Tatsache, dass an einem 28-Pin-Mikrocontroller nur ca. 10 Pins und auf den 8KB Speicher nur 3 belegt waren und das Ganze nicht richtig im Gamecontroller untergebracht werden konnte, störte mich ein wenig. Vor kurzem las ich dann folgendes auf obdev.at: <pre> New: Internal RC Oscillator Supported AVR-USB supports the internal RC oscillator of all AVRs with internal high frequency PLL, such as the ATTiny45 or ATTiny26. No external crystal is needed on these devices! See the EasyLogger example for details. </pre> Das war das, worauf ich gewartet hatte: Der ATTiny45 hat 8 Beine, wofür 2 für USB und weitere 3 für die Standardbeschaltung verwendet werden. Somit bleiben genau die benötigten drei Anschlüsse für das Gamepad frei. Die Beispielanwendung für die Implementierung ([http://www.obdev.at/products/avrusb/easylogger.html EasyLogger]) zielt schon sehr gut in die Richtung, in die ich gehen will. Der Großteil des Quelltextes konnte beibehalten werden, Teile kamen von Raph und wurden ziemlich stark umgebaut. Nachdem ich einige Wochen zuvor kläglich daran gescheitert bin, die Software von oben auf den ATTiny2313 zu portieren, nahm ich mir zum Ziel, den Quelltext so klein wie möglich zu gestalten. Nach etlichen Optimierversuchen und Brennvorgängen war es dann geschafft: Das kompilierte Programm ist exakt 2000 Byte groß. Leider hat der Device-Name etwas darunter gelitten - es ist allerdings noch deutlich erkennbar, worum es sich handelt. Ein weiteres Ziel war, die Elektronik im Controller unterzubringen, sodass nur noch ein USB-Kabel ohne weitere Elektronik am PC angeschlossen wird. Netterweise ist im Gamepad ziemlich viel Platz vorhanden, welcher erlaubt, selbst einen DIP-IC aufgelötet auf einer Platine zu fassen. Also flugs die Schaltung vom Steckbrett auf die Platine bringen. Nach dem ersten Test am PC war ich etwas irritiert: kein fröhliches "Plüm-Plim" vom PC, stattdessen kam nach einigen Wartesekunden ein "Plopp" aus den Lautsprechern: "Hardware wurde nicht erkannt". IC ausgelötet und wieder aufs Steckbrett: "Plüm-Plim" (Hardware erkannt). Auch nach langem Suchen war kein Fehler in der Schaltung zu finden. Also zurück an den Anfang: [[PLL im ATTiny45 kalibrieren]]. [[Bild:SNES-einbau.jpg|thumb|Einbau des V-USB-Controllers im SNES-Gamepad]] Nach ein paar Versuchen klappte es auch und ich konnte das Gamepad wieder schließen. Wenn mich jetzt die Lust packt heißt es nur noch Controller vorne am PC an einem freien USB-Port anschließen und losspielen. Da der Aufbau auf Lochraster zwar "ganz nett" ist, aber noch nicht der Weisheit letzter Schluss ist, habe eine kleine Schaltung + Platine in SMD in EAGLE erstellt: <gallery> Bild:Snes-usb_sch.png|Stromlaufplan Bild:SNES-brd.png|SMD-Layout der Schaltung Bild:Snes-usb-2313_sch.png|Stromlaufplan der ATtiny2313-Version </gallery> Die Schaltung ist zwar nicht gerade ideal zum Brennen des AVRs, aber evtl. könnte es klappen, wenn man die Anschlüsse für USB (oben) und für den SNES-Controllers (unten) ausnutzt. Leider kommt man nicht 'drum, einen Draht direkt an RESET zu löten. Platz für einen Testpin ist leider nicht mehr vorhanden. Die Anschlussbelegungen sind jeweils nach den Standards. Auf der SNES-Seite wie oben angegeben, auf USB-Seite so wie im USB-Standard angegeben (Näheres ist dem Stromlaufplan in der ZIP-Datei zu entnehmen). == Downloads == Die Firmware ist unkompiliert, da der OSCCAL-Wert nicht automatisch ermittelt wird. Weiterhin wurde kein Kompilat beigelegt, da das verwendete VID/PID-Paar (siehe usbconfig.h) nicht mir gehört und von jedem, der die Hardware einsetzt durch sein Paar ersetzt werden muss. (Wenn man die Schaltung für sich daheim privat betreibt, sollte es jedoch keine Probleme geben) *[[Datei:SNES-USB.zip]] Firmware OHNE automatische Kalibrierung *[[Datei:SNES-USB-autocal.zip]] Firmware MIT automatischer Kalibrierung und Hex-Datei *[[Datei:Snes-usb-2313.zip]] Firmware für ATtiny2313 === Nachtrag (07/2009) === Das Kalibrieren des PLLs kann seit einiger Zeit wegfallen - es gibt nun die Möglichkeit, die PLL anhand der USB-Framelänge beim Anschließen der USB-Devices zu kalibrieren. Habe es selber schon erfolgreich getestet. Näheres dazu: [http://vusb.wikidot.com/examples#toc4 Clocking the AVR from the RC oscillator with auto-calibration]. Achtung: DIE FIRMWARE IN SNES-USB.zip HIER ENTHÄLT DIESES FEATURE NOCH NICHT! ===Nachtrag (03/2010)=== Ich habe jetzt zusätzlich die Firmware für den ATtiny2313 und die für den ATtiny45 mit automatischer Kalibrierung der PLL hochgeladen. Am Notebook meiner Schwester gab es mit angeschlossenem Gamepad mit Autocal-Firmware ein paar Bluescreens. Ob diese tatsächlich von der Firmware ausgelöst wurde, kann ich nicht mit absoluter Sicherheit sagen. Ich weise einfach mal auf den [[Hobbyelektronik.org:Über_Hobbyelektronik.org#Haftungsausschluss|Haftungsausschluss]] hin. [[Category:PC]] [[Category:AVR]] [[Category:USB]] fad11fcca5e79f22603b04fd1ea8210e5d5af638 406 405 2010-03-04T23:23:19Z Chris 2 Überschriften korrigiert wikitext text/x-wiki Als Kind hatte ich mir mal (ja, aus eigener Tasche) einen Super Nintendo gekauft. Nachdem er die Jahre leider nicht überlebt hat und ich doch ab und an mal ein bisschen Verlangen nach SNES habe, griff ich auf Emulatoren für den PC zurück. So gut die Programme auch sind - man hat ein Problem: man muss auf der Tastatur spielen. Das mag bei manchen Spielen noch gehen, wenn man jedoch in brenzliche Situationen kommt, braucht man dann doch die etwas trainierteren Daumen. Irgendwann kam ich auf die Idee, einfach das Gamepad an den PC anzuschließen. Mit einem Nachbau eines SNES-Gamepads, das ich mal geschenkt bekommen habe, funktionierte das ziemlich gut. Im Pad selbst waren zwei CD4021 (Schieberegister) verbaut. Die Funktionsweise des Gamepads ist somit genauso simpel wie... simpel. Wenn die CPU in der Konsole den Controller auslesen will, werden die Daten per Latch in das Register geladen, von wo es dann seriell ausgelesen werden kann. [[Bild:SNES-stecker.jpg|thumb|Anschlussbelegung am Stecker]] Die Beschaltung im Controller ist folgendermaßen: {| ! Pin|| Farbe || Funktion |- | 1 || braun || GND |- | 2 || rot || Data |- | 3 || orange || Latch |- | 4 || gelb || Clock |- | 5 || weiß || Vcc |} Bei meiner ersten Entwicklung war das Gamepad am Parallel-Port angeschlossen und wurde von einem kleinen VB-Programm ausgelesen. Die Tastenanschläge wurden dann per DLL als Tastatur-Eingaben simuliert. Das ganze hatte nur ein paar Nachteile: * Die Software war nicht besonders schön * Der Parallelport wurde (mal wieder) zweckentfremdet * Man muss hinter den PC kriechen, wenn man wieder etwas drucken will * Das Ganze ist einfach nicht rund (vorangegangene Punkte) * Mein Notebook hat weder eine parallele noch serielle Schnittstelle Irgendwann entdeckte ich [http://www.obdev.at/products/vusb/index-de.html V-USB], eine Software-Implementierung von USB in AVRs. Als Projekt war [http://www.raphnet.net/electronique/snes_nes_usb/index_en.php SNES/NES gamepad (and mouse) to USB adapter] verlinkt. Die Schaltung habe ich mir dann relativ zügig aufgebaut, um zu testen, ob da wirklich das dahintersteckt, was ich mir erwartet hatte. Tatsächlich meldete Windows 2s nach dem Einstecken der Konstruktion eine neue Hardware. Nur die Tatsache, dass an einem 28-Pin-Mikrocontroller nur ca. 10 Pins und auf den 8KB Speicher nur 3 belegt waren und das Ganze nicht richtig im Gamecontroller untergebracht werden konnte, störte mich ein wenig. Vor kurzem las ich dann folgendes auf obdev.at: <pre> New: Internal RC Oscillator Supported AVR-USB supports the internal RC oscillator of all AVRs with internal high frequency PLL, such as the ATTiny45 or ATTiny26. No external crystal is needed on these devices! See the EasyLogger example for details. </pre> Das war das, worauf ich gewartet hatte: Der ATTiny45 hat 8 Beine, wofür 2 für USB und weitere 3 für die Standardbeschaltung verwendet werden. Somit bleiben genau die benötigten drei Anschlüsse für das Gamepad frei. Die Beispielanwendung für die Implementierung ([http://www.obdev.at/products/avrusb/easylogger.html EasyLogger]) zielt schon sehr gut in die Richtung, in die ich gehen will. Der Großteil des Quelltextes konnte beibehalten werden, Teile kamen von Raph und wurden ziemlich stark umgebaut. Nachdem ich einige Wochen zuvor kläglich daran gescheitert bin, die Software von oben auf den ATTiny2313 zu portieren, nahm ich mir zum Ziel, den Quelltext so klein wie möglich zu gestalten. Nach etlichen Optimierversuchen und Brennvorgängen war es dann geschafft: Das kompilierte Programm ist exakt 2000 Byte groß. Leider hat der Device-Name etwas darunter gelitten - es ist allerdings noch deutlich erkennbar, worum es sich handelt. Ein weiteres Ziel war, die Elektronik im Controller unterzubringen, sodass nur noch ein USB-Kabel ohne weitere Elektronik am PC angeschlossen wird. Netterweise ist im Gamepad ziemlich viel Platz vorhanden, welcher erlaubt, selbst einen DIP-IC aufgelötet auf einer Platine zu fassen. Also flugs die Schaltung vom Steckbrett auf die Platine bringen. Nach dem ersten Test am PC war ich etwas irritiert: kein fröhliches "Plüm-Plim" vom PC, stattdessen kam nach einigen Wartesekunden ein "Plopp" aus den Lautsprechern: "Hardware wurde nicht erkannt". IC ausgelötet und wieder aufs Steckbrett: "Plüm-Plim" (Hardware erkannt). Auch nach langem Suchen war kein Fehler in der Schaltung zu finden. Also zurück an den Anfang: [[PLL im ATTiny45 kalibrieren]]. [[Bild:SNES-einbau.jpg|thumb|Einbau des V-USB-Controllers im SNES-Gamepad]] Nach ein paar Versuchen klappte es auch und ich konnte das Gamepad wieder schließen. Wenn mich jetzt die Lust packt heißt es nur noch Controller vorne am PC an einem freien USB-Port anschließen und losspielen. Da der Aufbau auf Lochraster zwar "ganz nett" ist, aber noch nicht der Weisheit letzter Schluss ist, habe eine kleine Schaltung + Platine in SMD in EAGLE erstellt: <gallery> Bild:Snes-usb_sch.png|Stromlaufplan Bild:SNES-brd.png|SMD-Layout der Schaltung Bild:Snes-usb-2313_sch.png|Stromlaufplan der ATtiny2313-Version </gallery> Die Schaltung ist zwar nicht gerade ideal zum Brennen des AVRs, aber evtl. könnte es klappen, wenn man die Anschlüsse für USB (oben) und für den SNES-Controllers (unten) ausnutzt. Leider kommt man nicht 'drum, einen Draht direkt an RESET zu löten. Platz für einen Testpin ist leider nicht mehr vorhanden. Die Anschlussbelegungen sind jeweils nach den Standards. Auf der SNES-Seite wie oben angegeben, auf USB-Seite so wie im USB-Standard angegeben (Näheres ist dem Stromlaufplan in der ZIP-Datei zu entnehmen). = Downloads = Die Firmware ist unkompiliert, da der OSCCAL-Wert nicht automatisch ermittelt wird. Weiterhin wurde kein Kompilat beigelegt, da das verwendete VID/PID-Paar (siehe usbconfig.h) nicht mir gehört und von jedem, der die Hardware einsetzt durch sein Paar ersetzt werden muss. (Wenn man die Schaltung für sich daheim privat betreibt, sollte es jedoch keine Probleme geben) *[[Datei:SNES-USB.zip]] Firmware OHNE automatische Kalibrierung *[[Datei:SNES-USB-autocal.zip]] Firmware MIT automatischer Kalibrierung und Hex-Datei *[[Datei:Snes-usb-2313.zip]] Firmware für ATtiny2313 == Nachtrag (07/2009) == Das Kalibrieren des PLLs kann seit einiger Zeit wegfallen - es gibt nun die Möglichkeit, die PLL anhand der USB-Framelänge beim Anschließen der USB-Devices zu kalibrieren. Habe es selber schon erfolgreich getestet. Näheres dazu: [http://vusb.wikidot.com/examples#toc4 Clocking the AVR from the RC oscillator with auto-calibration]. Achtung: DIE FIRMWARE IN SNES-USB.zip HIER ENTHÄLT DIESES FEATURE NOCH NICHT! ===Nachtrag (03/2010)=== Ich habe jetzt zusätzlich die Firmware für den ATtiny2313 und die für den ATtiny45 mit automatischer Kalibrierung der PLL hochgeladen. Am Notebook meiner Schwester gab es mit angeschlossenem Gamepad mit Autocal-Firmware ein paar Bluescreens. Ob diese tatsächlich von der Firmware ausgelöst wurde, kann ich nicht mit absoluter Sicherheit sagen. Ich weise einfach mal auf den [[Hobbyelektronik.org:Über_Hobbyelektronik.org#Haftungsausschluss|Haftungsausschluss]] hin. [[Category:PC]] [[Category:AVR]] [[Category:USB]] a770dbc90d6dbe5e865dd3e119913f62d2932604 444 406 2010-06-13T11:46:21Z Chris 2 wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = 0xDD | FuseL = 0xE1 | FuseE = 0xFF }} Als Kind hatte ich mir mal (ja, aus eigener Tasche) einen Super Nintendo gekauft. Nachdem er die Jahre leider nicht überlebt hat und ich doch ab und an mal ein bisschen Verlangen nach SNES habe, griff ich auf Emulatoren für den PC zurück. So gut die Programme auch sind - man hat ein Problem: man muss auf der Tastatur spielen. Das mag bei manchen Spielen noch gehen, wenn man jedoch in brenzliche Situationen kommt, braucht man dann doch die etwas trainierteren Daumen. Irgendwann kam ich auf die Idee, einfach das Gamepad an den PC anzuschließen. Mit einem Nachbau eines SNES-Gamepads, das ich mal geschenkt bekommen habe, funktionierte das ziemlich gut. Im Pad selbst waren zwei CD4021 (Schieberegister) verbaut. Die Funktionsweise des Gamepads ist somit genauso simpel wie... simpel. Wenn die CPU in der Konsole den Controller auslesen will, werden die Daten per Latch in das Register geladen, von wo es dann seriell ausgelesen werden kann. [[Bild:SNES-stecker.jpg|thumb|Anschlussbelegung am Stecker]] Die Beschaltung im Controller ist folgendermaßen: {| ! Pin|| Farbe || Funktion |- | 1 || braun || GND |- | 2 || rot || Data |- | 3 || orange || Latch |- | 4 || gelb || Clock |- | 5 || weiß || Vcc |} Bei meiner ersten Entwicklung war das Gamepad am Parallel-Port angeschlossen und wurde von einem kleinen VB-Programm ausgelesen. Die Tastenanschläge wurden dann per DLL als Tastatur-Eingaben simuliert. Das ganze hatte nur ein paar Nachteile: * Die Software war nicht besonders schön * Der Parallelport wurde (mal wieder) zweckentfremdet * Man muss hinter den PC kriechen, wenn man wieder etwas drucken will * Das Ganze ist einfach nicht rund (vorangegangene Punkte) * Mein Notebook hat weder eine parallele noch serielle Schnittstelle Irgendwann entdeckte ich [http://www.obdev.at/products/vusb/index-de.html V-USB], eine Software-Implementierung von USB in AVRs. Als Projekt war [http://www.raphnet.net/electronique/snes_nes_usb/index_en.php SNES/NES gamepad (and mouse) to USB adapter] verlinkt. Die Schaltung habe ich mir dann relativ zügig aufgebaut, um zu testen, ob da wirklich das dahintersteckt, was ich mir erwartet hatte. Tatsächlich meldete Windows 2s nach dem Einstecken der Konstruktion eine neue Hardware. Nur die Tatsache, dass an einem 28-Pin-Mikrocontroller nur ca. 10 Pins und auf den 8KB Speicher nur 3 belegt waren und das Ganze nicht richtig im Gamecontroller untergebracht werden konnte, störte mich ein wenig. Vor kurzem las ich dann folgendes auf obdev.at: <pre> New: Internal RC Oscillator Supported AVR-USB supports the internal RC oscillator of all AVRs with internal high frequency PLL, such as the ATTiny45 or ATTiny26. No external crystal is needed on these devices! See the EasyLogger example for details. </pre> Das war das, worauf ich gewartet hatte: Der ATTiny45 hat 8 Beine, wofür 2 für USB und weitere 3 für die Standardbeschaltung verwendet werden. Somit bleiben genau die benötigten drei Anschlüsse für das Gamepad frei. Die Beispielanwendung für die Implementierung ([http://www.obdev.at/products/avrusb/easylogger.html EasyLogger]) zielt schon sehr gut in die Richtung, in die ich gehen will. Der Großteil des Quelltextes konnte beibehalten werden, Teile kamen von Raph und wurden ziemlich stark umgebaut. Nachdem ich einige Wochen zuvor kläglich daran gescheitert bin, die Software von oben auf den ATTiny2313 zu portieren, nahm ich mir zum Ziel, den Quelltext so klein wie möglich zu gestalten. Nach etlichen Optimierversuchen und Brennvorgängen war es dann geschafft: Das kompilierte Programm ist exakt 2000 Byte groß. Leider hat der Device-Name etwas darunter gelitten - es ist allerdings noch deutlich erkennbar, worum es sich handelt. Ein weiteres Ziel war, die Elektronik im Controller unterzubringen, sodass nur noch ein USB-Kabel ohne weitere Elektronik am PC angeschlossen wird. Netterweise ist im Gamepad ziemlich viel Platz vorhanden, welcher erlaubt, selbst einen DIP-IC aufgelötet auf einer Platine zu fassen. Also flugs die Schaltung vom Steckbrett auf die Platine bringen. Nach dem ersten Test am PC war ich etwas irritiert: kein fröhliches "Plüm-Plim" vom PC, stattdessen kam nach einigen Wartesekunden ein "Plopp" aus den Lautsprechern: "Hardware wurde nicht erkannt". IC ausgelötet und wieder aufs Steckbrett: "Plüm-Plim" (Hardware erkannt). Auch nach langem Suchen war kein Fehler in der Schaltung zu finden. Also zurück an den Anfang: [[PLL im ATTiny45 kalibrieren]]. [[Bild:SNES-einbau.jpg|thumb|Einbau des V-USB-Controllers im SNES-Gamepad]] Nach ein paar Versuchen klappte es auch und ich konnte das Gamepad wieder schließen. Wenn mich jetzt die Lust packt heißt es nur noch Controller vorne am PC an einem freien USB-Port anschließen und losspielen. Da der Aufbau auf Lochraster zwar "ganz nett" ist, aber noch nicht der Weisheit letzter Schluss ist, habe eine kleine Schaltung + Platine in SMD in EAGLE erstellt: <gallery> Bild:Snes-usb_sch.png|Stromlaufplan Bild:SNES-brd.png|SMD-Layout der Schaltung Bild:Snes-usb-2313_sch.png|Stromlaufplan der ATtiny2313-Version </gallery> Die Schaltung ist zwar nicht gerade ideal zum Brennen des AVRs, aber evtl. könnte es klappen, wenn man die Anschlüsse für USB (oben) und für den SNES-Controllers (unten) ausnutzt. Leider kommt man nicht 'drum, einen Draht direkt an RESET zu löten. Platz für einen Testpin ist leider nicht mehr vorhanden. Die Anschlussbelegungen sind jeweils nach den Standards. Auf der SNES-Seite wie oben angegeben, auf USB-Seite so wie im USB-Standard angegeben (Näheres ist dem Stromlaufplan in der ZIP-Datei zu entnehmen). = Downloads = Die Firmware ist unkompiliert, da der OSCCAL-Wert nicht automatisch ermittelt wird. Weiterhin wurde kein Kompilat beigelegt, da das verwendete VID/PID-Paar (siehe usbconfig.h) nicht mir gehört und von jedem, der die Hardware einsetzt durch sein Paar ersetzt werden muss. (Wenn man die Schaltung für sich daheim privat betreibt, sollte es jedoch keine Probleme geben) *[[Datei:SNES-USB.zip]] Firmware OHNE automatische Kalibrierung *[[Datei:SNES-USB-autocal.zip]] Firmware MIT automatischer Kalibrierung und Hex-Datei *[[Datei:Snes-usb-2313.zip]] Firmware für ATtiny2313 == Nachtrag (07/2009) == Das Kalibrieren des PLLs kann seit einiger Zeit wegfallen - es gibt nun die Möglichkeit, die PLL anhand der USB-Framelänge beim Anschließen der USB-Devices zu kalibrieren. Habe es selber schon erfolgreich getestet. Näheres dazu: [http://vusb.wikidot.com/examples#toc4 Clocking the AVR from the RC oscillator with auto-calibration]. Achtung: DIE FIRMWARE IN SNES-USB.zip HIER ENTHÄLT DIESES FEATURE NOCH NICHT! ===Nachtrag (03/2010)=== Ich habe jetzt zusätzlich die Firmware für den ATtiny2313 und die für den ATtiny45 mit automatischer Kalibrierung der PLL hochgeladen. Am Notebook meiner Schwester gab es mit angeschlossenem Gamepad mit Autocal-Firmware ein paar Bluescreens. Ob diese tatsächlich von der Firmware ausgelöst wurde, kann ich nicht mit absoluter Sicherheit sagen. Ich weise einfach mal auf den [[Hobbyelektronik.org:Über_Hobbyelektronik.org#Haftungsausschluss|Haftungsausschluss]] hin. [[Category:PC]] [[Category:AVR]] [[Category:USB]] a25f8f9035498bb6a5eb1d4988998fb410cc7f5f Panasonic-Zapper 0 112 407 377 2010-03-04T23:24:38Z Chris 2 Überschriften korrigiert wikitext text/x-wiki Mein Vater hat, wie viele, die Angewohnheit, vor dem Fernseher einzuschlafen. Soweit nicht schlimm, allerdings geht es auf Dauer unnötigerweise auf die Stromrechnung und die Flimmerkiste wird dadurch auch nicht jünger. Manchmal kommt noch jemand am Wohnzimmer vorbei und schaltet das Gerät ab. Das muss doch auch einfacher gehen... =Ideen= Meine erste Idee war, dem Teil per Zeitschaltuhr zumindest für eine Minute pro Nacht den Saft abzudrehen. Anders als unser alter Telefunken geht der Panasonic nach Spannungsrückkehr _nicht_ in den Stand-By. Genauso ist ihm die 12V-Steuerspannung am Scart grundsätzlich egal, sodass man selbes Spiel mit dem SAT-Receiver treiben könnte. Die zweite Idee war (auch noch vor dem Erlangen von Kenntnissen in der µC-Programmierung) war, eine Universal-Fernbedienung mit einem Wecker zu verheiraten. Blöd nur: Der Wecker schaltet seinen Alarmkontakt für einige Minuten, die Fernbedienung wird also unnötig lange betätigt, die Batterien gehen schnell leer und man hat eine Aperatur, die zwei Mal am Tag die Glotze abdreht und gleichzeitig die Fernbedienung zum wiederanschalten in dieser Zeit blockiert. Das hat weder [http://de.wikipedia.org/wiki/Woman_acceptance_factor WAF] noch <span title="father acceptance factor">FAF</span>. Das mit der Universal-Fernbedienung habe ich daher auch relativ schnell verworfen, die Idee mit dem Wecker blieb noch eine Weile. =Die Lösung= Der nächste Ansatz war, die Fernbedienung in einem Mikrocontroller nachzubilden. Seit dem [http://ladyada.net/make/tvbgone/ TV-B-Gone] ist das massenhafte Abschalten von TV-Geräten ein Geek-Volkssport geworden. Ein guter Ansatz. Als nächstes schaute ich mir die [http://lirc.sourceforge.net/remotes/ Fernbedienungs-Bibliothek von LIRC] an. Von Panasonic gibt es genügend Codes. Allerdings keinen, der (auf den ersten Blick) exakt auf die Fernbedienung hier passt. Also: Fototranse an die Soundkarte anklemmen, aufnehmen ([[Datei:Panasonic.wav]]) und genauer anschauen (z. B. mit [http://audacity.sourceforge.net/ Audacity]). Netterweise war die Soundkarte lahm und übersteuert genug, dass man keinen 38kHz-Filter auf die Aufnahme anwenden musste (an den Flanken sieht man noch ein bisschen was). Mit Papier und Bleistift habe ich dann das Protokoll analysiert und vollständige Übereinstimmung zu einer Definition von LIRC gefunden. Muss das Signal nur noch nachgebaut werden. Die Ausgabe der Bytes ist kein Problem, nur das Trägersignal von 38kHz macht mir etwas Sorgen. Zwar kann man dies auch mit C halbwegs gut zu Fuß ausgeben, muss aber beim Timing etwas aufpassen. Netterweise kann man selbst mit dem sonst recht schwachen ATtiny13 hardwareseitig Signale mit einem Rechteck moduliert ausgeben. Spart man sich einen NE555 bzw. nervige Timinganpassungen. Den Code hierfür habe ich auch beim TV-B-Gone wiederentdeckt. Nachdem der Fernbedienungscode dem Mikrocontroller beigebracht und das Timing noch ein bisschen angepasst wurde (kommt auf 99% an das Original heran), ging die Überlegerei wieder los: wie auslösen? Hier kommt der Wecker wieder ins Spiel: Statt meinen Vater zu wecken (damit er den Fernseher abstellt), kann der doch die Stromversorgung schalten. Blöd auch hier wieder: Zwei Spannungsquellen, weil der AVR halbwegs genau 5V sehen will, da sonst der RC-Taktgeber einen zu niedrigen Takt ausgibt und von der IR-LED nur noch Kauderwelsch kommt. Außerdem sind Wecker unerhört teuer - da lohnt es sich schon fast, eine RTC samt Display an den kleinen anzuschließen. Totaler Overkill ==Die bessere Lösung== Irgendwann fiel es mir wie Schuppen von den Augen: Das deutlichste Indiz für die (Nicht-)Benutzung des Fernsehers ist die Bedienung! Es reicht zu beobachten, ob der Verseher aktiv genutzt wird, sprich: ob man den Sender wechselt, die Lautstärke verändert oder einfach nur wahllos auf der Fernbedienung herumdrückt. Ein IR-Empfänger mit Tageslicht- und 38kHz-Filter liegt noch herum, also anschließen und gucken, was passiert. Der Einfachheit halber hängt das Teil am Interrupt-Eingang des AVR. Beim auslösen wird ein Zähler gesetzt und per Timer langsam heruntergezählt. Damit die Glotze nicht an der spannensten Stelle eines längeren Films einfach ausgeht, blinkt in den letzten 15 Minuten eine LED. Diese wird auch beim Auslösen des Interrupts des IR-Empfängers kurz aktiviert. Beim Herumspielen mit der Schaltung habe ich jedoch eine Feststellung gemacht: ab und zu reagiert der Empfänger auch auf andere Lichteinflüsse (oder er hat einfach nur einen Knall) und gibt einen kurzen Impuls ab. Der Puls reicht aus, um den Timer wieder zurückzusetzen, also sehr ungeschickt. ==Filter== Ein Filter muss her. Da ich keine größere Lust hatte und gleichzeitig mit meinem DSO spielen wollte, wurde er heuristisch aufgebaut. Mehr oder weniger wahllos Bauteile gesetzt, bis das herauskam, was ich wollte. [[Bild:Panasonic_filter.png]] Kurz zur Funktionsweise: R1 zieht den Ausgang OpenCollector-Ausgang des IR-Empfängers auf 5V, gleiches macht R3 mit dem Elko. Hat der Empfänger ein Signal erkannt, zieht er seinen Ausgang auf Low und dadurch die Spannung am Elko auf etwa 0,7V (bedingt durch die Diode). Die Diode bewirkt, dass der Kondensator nur durch den 10k-Widerstand (und nicht auch durch R1 und R2) geladen wird. R2 kann man bei entsprechender Wahl von R1 auch weglassen - nachdem es so aber recht gut klappte: never change a running system ;) <gallery> Bild:Panasonic_fb.png|Gefiltertes Signal einer Fernbedienung Bild:Panasonic_stoerung.png|Störung am Empfänger </gallery> CH1 (cyan) ist jeweils das "gefilterte" Ausgangssignal, CH2 (gelb) das, was vom Empfänger kommt. Die blauen Linien sind stehen für die Spannung, ab der der AVR eine Eingangsspannung als Low-Pegel erkennt. Beim Empfang einer Fernbedienung sieht man, dass die Spannung zuverlässig unterschritten wird. Im rechten Bild wurde mit einem Laserpointer mit hohem IR-Anteil das Auslösen provoziert beim ersten Schalten des Empfängers wäre der Timer bereits zurückgesetzt worden, durch die Entladekurve, bleibt die Spannung allerdings noch über dem Ansprechwert. Bei der zweiten Störung, die ich empfangen habe, löste die Schaltung gerade so nach knapp 9ms aus. Allerdings ist auch der Spannungspegel vor der erneuten Störung zu beachten: durch die vorhergehende Spitze wurde der Kondensator schon ein Stück entladen, eine Auslösung fällt bei nachfolgenden Signalen also leichter. =Schaltung= So schauts aus: <gallery> Bild:Panasonic_sch.png|Stromlaufplan Bild:Panasonic_brd.png|Board (optimiert für Lochraster) Bild:Panasonic_real.jpg|Aufbau in Natura Bild:Panasonic_fuses.png|Fuses im ATtiny13 (H:0xF9, L:0x7A) </gallery> =Download= [[Datei:PanasonicOff.zip]] C-Code und EAGLE-Dateien [[Category:AVR]] 4a429eec7b21ce3dc7ff096797198561e9d6881a 413 407 2010-05-03T10:45:33Z Chris 2 Nachtrag wikitext text/x-wiki Mein Vater hat, wie viele, die Angewohnheit, vor dem Fernseher einzuschlafen. Soweit nicht schlimm, allerdings geht es auf Dauer unnötigerweise auf die Stromrechnung und die Flimmerkiste wird dadurch auch nicht jünger. Manchmal kommt noch jemand am Wohnzimmer vorbei und schaltet das Gerät ab. Das muss doch auch einfacher gehen... =Ideen= Meine erste Idee war, dem Teil per Zeitschaltuhr zumindest für eine Minute pro Nacht den Saft abzudrehen. Anders als unser alter Telefunken geht der Panasonic nach Spannungsrückkehr _nicht_ in den Stand-By. Genauso ist ihm die 12V-Steuerspannung am Scart grundsätzlich egal, sodass man selbes Spiel mit dem SAT-Receiver treiben könnte. Die zweite Idee war (auch noch vor dem Erlangen von Kenntnissen in der µC-Programmierung) war, eine Universal-Fernbedienung mit einem Wecker zu verheiraten. Blöd nur: Der Wecker schaltet seinen Alarmkontakt für einige Minuten, die Fernbedienung wird also unnötig lange betätigt, die Batterien gehen schnell leer und man hat eine Aperatur, die zwei Mal am Tag die Glotze abdreht und gleichzeitig die Fernbedienung zum wiederanschalten in dieser Zeit blockiert. Das hat weder [http://de.wikipedia.org/wiki/Woman_acceptance_factor WAF] noch <span title="father acceptance factor">FAF</span>. Das mit der Universal-Fernbedienung habe ich daher auch relativ schnell verworfen, die Idee mit dem Wecker blieb noch eine Weile. =Die Lösung= Der nächste Ansatz war, die Fernbedienung in einem Mikrocontroller nachzubilden. Seit dem [http://ladyada.net/make/tvbgone/ TV-B-Gone] ist das massenhafte Abschalten von TV-Geräten ein Geek-Volkssport geworden. Ein guter Ansatz. Als nächstes schaute ich mir die [http://lirc.sourceforge.net/remotes/ Fernbedienungs-Bibliothek von LIRC] an. Von Panasonic gibt es genügend Codes. Allerdings keinen, der (auf den ersten Blick) exakt auf die Fernbedienung hier passt. Also: Fototranse an die Soundkarte anklemmen, aufnehmen ([[Datei:Panasonic.wav]]) und genauer anschauen (z. B. mit [http://audacity.sourceforge.net/ Audacity]). Netterweise war die Soundkarte lahm und übersteuert genug, dass man keinen 38kHz-Filter auf die Aufnahme anwenden musste (an den Flanken sieht man noch ein bisschen was). Mit Papier und Bleistift habe ich dann das Protokoll analysiert und vollständige Übereinstimmung zu einer Definition von LIRC gefunden. Muss das Signal nur noch nachgebaut werden. Die Ausgabe der Bytes ist kein Problem, nur das Trägersignal von 38kHz macht mir etwas Sorgen. Zwar kann man dies auch mit C halbwegs gut zu Fuß ausgeben, muss aber beim Timing etwas aufpassen. Netterweise kann man selbst mit dem sonst recht schwachen ATtiny13 hardwareseitig Signale mit einem Rechteck moduliert ausgeben. Spart man sich einen NE555 bzw. nervige Timinganpassungen. Den Code hierfür habe ich auch beim TV-B-Gone wiederentdeckt. Nachdem der Fernbedienungscode dem Mikrocontroller beigebracht und das Timing noch ein bisschen angepasst wurde (kommt auf 99% an das Original heran), ging die Überlegerei wieder los: wie auslösen? Hier kommt der Wecker wieder ins Spiel: Statt meinen Vater zu wecken (damit er den Fernseher abstellt), kann der doch die Stromversorgung schalten. Blöd auch hier wieder: Zwei Spannungsquellen, weil der AVR halbwegs genau 5V sehen will, da sonst der RC-Taktgeber einen zu niedrigen Takt ausgibt und von der IR-LED nur noch Kauderwelsch kommt. Außerdem sind Wecker unerhört teuer - da lohnt es sich schon fast, eine RTC samt Display an den kleinen anzuschließen. Totaler Overkill ==Die bessere Lösung== Irgendwann fiel es mir wie Schuppen von den Augen: Das deutlichste Indiz für die (Nicht-)Benutzung des Fernsehers ist die Bedienung! Es reicht zu beobachten, ob der Verseher aktiv genutzt wird, sprich: ob man den Sender wechselt, die Lautstärke verändert oder einfach nur wahllos auf der Fernbedienung herumdrückt. Ein IR-Empfänger mit Tageslicht- und 38kHz-Filter liegt noch herum, also anschließen und gucken, was passiert. Der Einfachheit halber hängt das Teil am Interrupt-Eingang des AVR. Beim auslösen wird ein Zähler gesetzt und per Timer langsam heruntergezählt. Damit die Glotze nicht an der spannensten Stelle eines längeren Films einfach ausgeht, blinkt in den letzten 15 Minuten eine LED. Diese wird auch beim Auslösen des Interrupts des IR-Empfängers kurz aktiviert. Beim Herumspielen mit der Schaltung habe ich jedoch eine Feststellung gemacht: ab und zu reagiert der Empfänger auch auf andere Lichteinflüsse (oder er hat einfach nur einen Knall) und gibt einen kurzen Impuls ab. Der Puls reicht aus, um den Timer wieder zurückzusetzen, also sehr ungeschickt. ==Filter== Ein Filter muss her. Da ich keine größere Lust hatte und gleichzeitig mit meinem DSO spielen wollte, wurde er heuristisch aufgebaut. Mehr oder weniger wahllos Bauteile gesetzt, bis das herauskam, was ich wollte. [[Bild:Panasonic_filter.png]] Kurz zur Funktionsweise: R1 zieht den Ausgang OpenCollector-Ausgang des IR-Empfängers auf 5V, gleiches macht R3 mit dem Elko. Hat der Empfänger ein Signal erkannt, zieht er seinen Ausgang auf Low und dadurch die Spannung am Elko auf etwa 0,7V (bedingt durch die Diode). Die Diode bewirkt, dass der Kondensator nur durch den 10k-Widerstand (und nicht auch durch R1 und R2) geladen wird. R2 kann man bei entsprechender Wahl von R1 auch weglassen - nachdem es so aber recht gut klappte: never change a running system ;) <gallery> Bild:Panasonic_fb.png|Gefiltertes Signal einer Fernbedienung Bild:Panasonic_stoerung.png|Störung am Empfänger </gallery> CH1 (cyan) ist jeweils das "gefilterte" Ausgangssignal, CH2 (gelb) das, was vom Empfänger kommt. Die blauen Linien sind stehen für die Spannung, ab der der AVR eine Eingangsspannung als Low-Pegel erkennt. Beim Empfang einer Fernbedienung sieht man, dass die Spannung zuverlässig unterschritten wird. Im rechten Bild wurde mit einem Laserpointer mit hohem IR-Anteil das Auslösen provoziert beim ersten Schalten des Empfängers wäre der Timer bereits zurückgesetzt worden, durch die Entladekurve, bleibt die Spannung allerdings noch über dem Ansprechwert. Bei der zweiten Störung, die ich empfangen habe, löste die Schaltung gerade so nach knapp 9ms aus. Allerdings ist auch der Spannungspegel vor der erneuten Störung zu beachten: durch die vorhergehende Spitze wurde der Kondensator schon ein Stück entladen, eine Auslösung fällt bei nachfolgenden Signalen also leichter. =Schaltung= So schauts aus: <gallery> Bild:Panasonic_sch.png|Stromlaufplan Bild:Panasonic_brd.png|Board (optimiert für Lochraster) Bild:Panasonic_real.jpg|Aufbau in Natura Bild:Panasonic_fuses.png|Fuses im ATtiny13 (H:0xF9, L:0x7A) </gallery> =Download= [[Datei:PanasonicOff.zip]] C-Code und EAGLE-Dateien =Nachtrag= Das Teil hat ein riesengroßes Problem, das den Spareffekt zunichte machen kann: Schaltet man den Fernseher per Fernbedienung ab, wird dies natürlich auch getriggert. Nach der voreingestellten Zeit wird dann wieder der Power-Befehl gesendet. Problem an der Sache: Zumindest unser Panasonic lässt sich per Power-Knopf auf der Fernbedienung sowohl aus- als auch einschalten. Wenn es dumm läuft, ist die Flimmerkiste nach abgelaufener Zeit wieder an (und geht dann ohne Zutun auch nicht wieder aus). Gleiches passiert natürlich auch, wenn der Empfänger längerfristig gestört wird und somit versehentlich getriggert wird. Lösung: Wenn man sieht, dass die Standby-LED leuchtet: mechanisch abschalten. Technisch gäbe es für das Problem mehrere Lösungen: * Schalt- oder Videosignal vom SCART verwenden, um den Betriebszustand zu ermitteln * Stromverbrauch der Kiste messen (z. B. mit Spule um die Zuleitung) * Temperatur am Gehäuse messen Da ich jedoch auf die technischen Lösungen zurückgreife, landet die Schaltung zusätzlich in der Kategorie Murks. [[Category:AVR]] [[Category:Murks]] 32aa3af5a0304ccc62e6c2a9156d7e78f989ecee 445 413 2010-06-13T11:48:27Z Chris 2 Infobox AVR hinzugefügt wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny13 | Takt = 9,6 | FuseH = 0xF9 | FuseL = 0x7A }} Mein Vater hat, wie viele, die Angewohnheit, vor dem Fernseher einzuschlafen. Soweit nicht schlimm, allerdings geht es auf Dauer unnötigerweise auf die Stromrechnung und die Flimmerkiste wird dadurch auch nicht jünger. Manchmal kommt noch jemand am Wohnzimmer vorbei und schaltet das Gerät ab. Das muss doch auch einfacher gehen... =Ideen= Meine erste Idee war, dem Teil per Zeitschaltuhr zumindest für eine Minute pro Nacht den Saft abzudrehen. Anders als unser alter Telefunken geht der Panasonic nach Spannungsrückkehr _nicht_ in den Stand-By. Genauso ist ihm die 12V-Steuerspannung am Scart grundsätzlich egal, sodass man selbes Spiel mit dem SAT-Receiver treiben könnte. Die zweite Idee war (auch noch vor dem Erlangen von Kenntnissen in der µC-Programmierung) war, eine Universal-Fernbedienung mit einem Wecker zu verheiraten. Blöd nur: Der Wecker schaltet seinen Alarmkontakt für einige Minuten, die Fernbedienung wird also unnötig lange betätigt, die Batterien gehen schnell leer und man hat eine Aperatur, die zwei Mal am Tag die Glotze abdreht und gleichzeitig die Fernbedienung zum wiederanschalten in dieser Zeit blockiert. Das hat weder [http://de.wikipedia.org/wiki/Woman_acceptance_factor WAF] noch <span title="father acceptance factor">FAF</span>. Das mit der Universal-Fernbedienung habe ich daher auch relativ schnell verworfen, die Idee mit dem Wecker blieb noch eine Weile. =Die Lösung= Der nächste Ansatz war, die Fernbedienung in einem Mikrocontroller nachzubilden. Seit dem [http://ladyada.net/make/tvbgone/ TV-B-Gone] ist das massenhafte Abschalten von TV-Geräten ein Geek-Volkssport geworden. Ein guter Ansatz. Als nächstes schaute ich mir die [http://lirc.sourceforge.net/remotes/ Fernbedienungs-Bibliothek von LIRC] an. Von Panasonic gibt es genügend Codes. Allerdings keinen, der (auf den ersten Blick) exakt auf die Fernbedienung hier passt. Also: Fototranse an die Soundkarte anklemmen, aufnehmen ([[Datei:Panasonic.wav]]) und genauer anschauen (z. B. mit [http://audacity.sourceforge.net/ Audacity]). Netterweise war die Soundkarte lahm und übersteuert genug, dass man keinen 38kHz-Filter auf die Aufnahme anwenden musste (an den Flanken sieht man noch ein bisschen was). Mit Papier und Bleistift habe ich dann das Protokoll analysiert und vollständige Übereinstimmung zu einer Definition von LIRC gefunden. Muss das Signal nur noch nachgebaut werden. Die Ausgabe der Bytes ist kein Problem, nur das Trägersignal von 38kHz macht mir etwas Sorgen. Zwar kann man dies auch mit C halbwegs gut zu Fuß ausgeben, muss aber beim Timing etwas aufpassen. Netterweise kann man selbst mit dem sonst recht schwachen ATtiny13 hardwareseitig Signale mit einem Rechteck moduliert ausgeben. Spart man sich einen NE555 bzw. nervige Timinganpassungen. Den Code hierfür habe ich auch beim TV-B-Gone wiederentdeckt. Nachdem der Fernbedienungscode dem Mikrocontroller beigebracht und das Timing noch ein bisschen angepasst wurde (kommt auf 99% an das Original heran), ging die Überlegerei wieder los: wie auslösen? Hier kommt der Wecker wieder ins Spiel: Statt meinen Vater zu wecken (damit er den Fernseher abstellt), kann der doch die Stromversorgung schalten. Blöd auch hier wieder: Zwei Spannungsquellen, weil der AVR halbwegs genau 5V sehen will, da sonst der RC-Taktgeber einen zu niedrigen Takt ausgibt und von der IR-LED nur noch Kauderwelsch kommt. Außerdem sind Wecker unerhört teuer - da lohnt es sich schon fast, eine RTC samt Display an den kleinen anzuschließen. Totaler Overkill ==Die bessere Lösung== Irgendwann fiel es mir wie Schuppen von den Augen: Das deutlichste Indiz für die (Nicht-)Benutzung des Fernsehers ist die Bedienung! Es reicht zu beobachten, ob der Verseher aktiv genutzt wird, sprich: ob man den Sender wechselt, die Lautstärke verändert oder einfach nur wahllos auf der Fernbedienung herumdrückt. Ein IR-Empfänger mit Tageslicht- und 38kHz-Filter liegt noch herum, also anschließen und gucken, was passiert. Der Einfachheit halber hängt das Teil am Interrupt-Eingang des AVR. Beim auslösen wird ein Zähler gesetzt und per Timer langsam heruntergezählt. Damit die Glotze nicht an der spannensten Stelle eines längeren Films einfach ausgeht, blinkt in den letzten 15 Minuten eine LED. Diese wird auch beim Auslösen des Interrupts des IR-Empfängers kurz aktiviert. Beim Herumspielen mit der Schaltung habe ich jedoch eine Feststellung gemacht: ab und zu reagiert der Empfänger auch auf andere Lichteinflüsse (oder er hat einfach nur einen Knall) und gibt einen kurzen Impuls ab. Der Puls reicht aus, um den Timer wieder zurückzusetzen, also sehr ungeschickt. ==Filter== Ein Filter muss her. Da ich keine größere Lust hatte und gleichzeitig mit meinem DSO spielen wollte, wurde er heuristisch aufgebaut. Mehr oder weniger wahllos Bauteile gesetzt, bis das herauskam, was ich wollte. [[Bild:Panasonic_filter.png]] Kurz zur Funktionsweise: R1 zieht den Ausgang OpenCollector-Ausgang des IR-Empfängers auf 5V, gleiches macht R3 mit dem Elko. Hat der Empfänger ein Signal erkannt, zieht er seinen Ausgang auf Low und dadurch die Spannung am Elko auf etwa 0,7V (bedingt durch die Diode). Die Diode bewirkt, dass der Kondensator nur durch den 10k-Widerstand (und nicht auch durch R1 und R2) geladen wird. R2 kann man bei entsprechender Wahl von R1 auch weglassen - nachdem es so aber recht gut klappte: never change a running system ;) <gallery> Bild:Panasonic_fb.png|Gefiltertes Signal einer Fernbedienung Bild:Panasonic_stoerung.png|Störung am Empfänger </gallery> CH1 (cyan) ist jeweils das "gefilterte" Ausgangssignal, CH2 (gelb) das, was vom Empfänger kommt. Die blauen Linien sind stehen für die Spannung, ab der der AVR eine Eingangsspannung als Low-Pegel erkennt. Beim Empfang einer Fernbedienung sieht man, dass die Spannung zuverlässig unterschritten wird. Im rechten Bild wurde mit einem Laserpointer mit hohem IR-Anteil das Auslösen provoziert beim ersten Schalten des Empfängers wäre der Timer bereits zurückgesetzt worden, durch die Entladekurve, bleibt die Spannung allerdings noch über dem Ansprechwert. Bei der zweiten Störung, die ich empfangen habe, löste die Schaltung gerade so nach knapp 9ms aus. Allerdings ist auch der Spannungspegel vor der erneuten Störung zu beachten: durch die vorhergehende Spitze wurde der Kondensator schon ein Stück entladen, eine Auslösung fällt bei nachfolgenden Signalen also leichter. =Schaltung= So schauts aus: <gallery> Bild:Panasonic_sch.png|Stromlaufplan Bild:Panasonic_brd.png|Board (optimiert für Lochraster) Bild:Panasonic_real.jpg|Aufbau in Natura Bild:Panasonic_fuses.png|Fuses im ATtiny13 (H:0xF9, L:0x7A) </gallery> =Download= [[Datei:PanasonicOff.zip]] C-Code und EAGLE-Dateien =Nachtrag= Das Teil hat ein riesengroßes Problem, das den Spareffekt zunichte machen kann: Schaltet man den Fernseher per Fernbedienung ab, wird dies natürlich auch getriggert. Nach der voreingestellten Zeit wird dann wieder der Power-Befehl gesendet. Problem an der Sache: Zumindest unser Panasonic lässt sich per Power-Knopf auf der Fernbedienung sowohl aus- als auch einschalten. Wenn es dumm läuft, ist die Flimmerkiste nach abgelaufener Zeit wieder an (und geht dann ohne Zutun auch nicht wieder aus). Gleiches passiert natürlich auch, wenn der Empfänger längerfristig gestört wird und somit versehentlich getriggert wird. Lösung: Wenn man sieht, dass die Standby-LED leuchtet: mechanisch abschalten. Technisch gäbe es für das Problem mehrere Lösungen: * Schalt- oder Videosignal vom SCART verwenden, um den Betriebszustand zu ermitteln * Stromverbrauch der Kiste messen (z. B. mit Spule um die Zuleitung) * Temperatur am Gehäuse messen Da ich jedoch auf die technischen Lösungen zurückgreife, landet die Schaltung zusätzlich in der Kategorie Murks. [[Category:AVR]] [[Category:Murks]] 5b97d1ab3e270893d50bc090b822c79638d3793a Hauptseite 0 1 408 383 2010-03-04T23:29:45Z Chris 2 aktualisiert wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *04.03.2010 [[VBus-Decoder]] *24.02.2010 [[UnitColor]] *12.02.2010 [[Panasonic-Zapper]] *27.12.2009 [[USBLotIO]] *04.07.2009 [[Touchlight]] =Updates= *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) da1dc3a77b3db645ea0f1ea989b444e243b29084 425 408 2010-06-12T22:03:35Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *04.03.2010 [[VBus-Decoder]] *24.02.2010 [[UnitColor]] *12.02.2010 [[Panasonic-Zapper]] *27.12.2009 [[USBLotIO]] *04.07.2009 [[Touchlight]] =Updates= *04.07.2009 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) 7a35080cc90b5e23ac025a8d1f834ec2e490f3a3 426 425 2010-06-13T09:29:28Z Chris 2 /* Updates */ Oops, falsches Datum ;) wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *04.03.2010 [[VBus-Decoder]] *24.02.2010 [[UnitColor]] *12.02.2010 [[Panasonic-Zapper]] *27.12.2009 [[USBLotIO]] *04.07.2009 [[Touchlight]] =Updates= *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) 01a41667b26b2b1d2ce866f10bb124bfb0595943 Datei:Vbus putty vs rss.png 6 125 409 395 2010-03-09T19:32:22Z Chris 2 hat eine neue Version von „[[Datei:Vbus putty vs rss.png]]“ hochgeladen wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:VbusDecode.zip 6 122 410 391 2010-03-09T19:41:27Z Chris 2 hat eine neue Version von „[[Datei:VbusDecode.zip]]“ hochgeladen wikitext text/x-wiki Version 0.1beta vom 04.03.2010 c28d770f302ad6299f601a13723df32b9e8ea6c4 Touchlight 0 92 412 340 2010-05-03T10:33:56Z Chris 2 /* Download */ wikitext text/x-wiki Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. == Leuchtmittel == Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "untrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos sortieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen. Da dieser über zwei Hardware-PWMs verfügt, sollen diese auch genutzt werden. Deswegen werden die LED-Leisten in zwei Stränge unterteilt - die Anzahl wird einzig durch das Netzteil beschränkt - einem austemusterten SonyEricsson-Ladegerät. Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. == Bedienung == Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. [Kategorie:AVR] Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. == Theorie == [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> U(t) = U0*(1-e^(-t/(R*C)) Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. == Die Software == Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <pre> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~pin; //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & pin) && --sampletime); //Zeit messen KEYDDR |= pin; //Pin als Ausgang -> entladen return sampletime; } </pre> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <pre> ... i = 0; n = 6; while(--n) { i += getcap(1<<PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </pre> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <pre> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </pre> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. == Download == [[Datei:Touch_1.0.zip]] Enthält sowohl den simplen Touchsensor als auch die Version mit serieller Ausgabe. CPU-Takt muss jeweils 9,6MHz sein (Bei Fabrikneuen Tiny13ern muss die CKDIV8-Fuse entfernt werden, damit das Teil bei vollem Takt läuft), der Rest nach eigenem Ermessen. Stromlaufpläne ist bei beiden Sourcen gleich, bei TouchSense ist zusätzlich der (nicht-invertierte) UART auf PBO. Dort werden die Messwerte der beiden Sensoren Tab-getrennt ausgegeben. die Konstante MINDELAY für den UART-Pause in suart.c muss wahrscheinlich angepasst werden. [[Category:AVR]] f9e31d8767fa455044adf1d712d7000d9085d574 423 412 2010-06-12T22:00:55Z Chris 2 Abschnitt Praxis zur Veranschaulichung hinzugefügt. wikitext text/x-wiki Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. == Leuchtmittel == Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "untrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos sortieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen. Da dieser über zwei Hardware-PWMs verfügt, sollen diese auch genutzt werden. Deswegen werden die LED-Leisten in zwei Stränge unterteilt - die Anzahl wird einzig durch das Netzteil beschränkt - einem austemusterten SonyEricsson-Ladegerät. Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. == Bedienung == Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. [Kategorie:AVR] Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. == Theorie == [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> U(t) = U0*(1-e^(-t/(R*C)) Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. == Praxis == Um es noch ein wenig anschaulicher zu machen, habe ich das Oszilloskop auf die Schaltung angesetzt. Dazu wurde die Schaltung auf dem Breadboard aufgebaut. Die Ladewiderstände entsprechen wie im Schaltplan 1,1MOhm. Die Sensorfläche mit 28x28mm (7,8 cm²) und 1,5mm Dicke (Dielektrikum: Hartpapier) ist mit 5cm Leitung direkt (ohne Angstwiderstand) mit dem AVR verbunden. Aufgrund der nicht zu verachtenden Kapazität des Breadboards un des Tastkopfes (Impedanz weiß ich gerade nicht auswendig) dürften die Messwerte deutlich verzerrt sein! Die Bilder und Erklärungen dienen daher höchstens zum Veranschaulichen des vorherigen Abschnitts! <gallery> Bild:Touchlight untouched.png|Unberührte Sensorfläche Bild:Touchlight touched.png|Berührte Sensorfläche Bild:Touchlight burst untuched.png|"Abfrageburst" unberührt Bild:Touchlight burst touched.png|"Abfrageburst" berührt </gallery> Im ersten Bild ist der Spannungsverlauf zu sehen, bei dem die Sensorfläche nicht berührt wurde. Entgegen der Datenblattangabe erkennt der AVR den High-Pegel bei 2,58V, wobei es 26,6µs dauert, bis dieser Wert erreicht wird. Wird die komplette Sensorfläche mit der Hand abgedeckt, steigt die Dauer bis zum Schwellenwert auf 41µs, also etwa das 1,5-fache der Zeit der unberührten Sensorfläche. Bei einem CPU-Takt von 9,6MHz sind dies 394 Taktzyklen (im Vergleich zu 256 Taktzyklen vorher), die man recht entspannt messen kann. In den letzten beiden Bildern ist ein kompletter "Abfrageburst" (5 Einzelabfragen) zu sehen. Auch wenn es auf den ersten Blick irreführend ist, die Bildunterschriften sind korrekt. Bei den beiden Fotos habe ich (dummerweise) eine andere Zeitbasis gewählt. Auch bei den Bursts hat das Zeitverhältnis zwischen unberührt und berührt den Faktor 1,5. Wobei ich dazu sagen muss: '''Traue keiner Statistik, die du nicht selbst gefälscht hast!''' Die gemessenen Dauern schwanken insbesondere beim Berühren der Sensorfläche immens. Hauptursache dürfte wahrscheinlich der Elektrosmog sein, der die 50 bzw. 100Hz (Halbwellen) aus dem Stromnetz beisteuert... == Die Software == Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <pre> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~pin; //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & pin) && --sampletime); //Zeit messen KEYDDR |= pin; //Pin als Ausgang -> entladen return sampletime; } </pre> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <pre> ... i = 0; n = 6; while(--n) { i += getcap(1<<PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </pre> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <pre> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </pre> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. == Download == [[Datei:Touch_1.0.zip]] Enthält sowohl den simplen Touchsensor als auch die Version mit serieller Ausgabe. CPU-Takt muss jeweils 9,6MHz sein (Bei Fabrikneuen Tiny13ern muss die CKDIV8-Fuse entfernt werden, damit das Teil bei vollem Takt läuft), der Rest nach eigenem Ermessen. Stromlaufpläne ist bei beiden Sourcen gleich, bei TouchSense ist zusätzlich der (nicht-invertierte) UART auf PBO. Dort werden die Messwerte der beiden Sensoren Tab-getrennt ausgegeben. die Konstante MINDELAY für den UART-Pause in suart.c muss wahrscheinlich angepasst werden. [[Category:AVR]] f8bee45b836b55b79ce2f883de827878e6bc979e 424 423 2010-06-12T22:02:07Z Chris 2 Artikelstruktur noch ein bisschen aufgebohrt wikitext text/x-wiki Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. = Leuchtmittel = Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "untrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos sortieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen. Da dieser über zwei Hardware-PWMs verfügt, sollen diese auch genutzt werden. Deswegen werden die LED-Leisten in zwei Stränge unterteilt - die Anzahl wird einzig durch das Netzteil beschränkt - einem austemusterten SonyEricsson-Ladegerät. Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. = Bedienung = Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. [Kategorie:AVR] Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. = Theorie = [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> U(t) = U0*(1-e^(-t/(R*C)) Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. = Praxis = Um es noch ein wenig anschaulicher zu machen, habe ich das Oszilloskop auf die Schaltung angesetzt. Dazu wurde die Schaltung auf dem Breadboard aufgebaut. Die Ladewiderstände entsprechen wie im Schaltplan 1,1MOhm. Die Sensorfläche mit 28x28mm (7,8 cm²) und 1,5mm Dicke (Dielektrikum: Hartpapier) ist mit 5cm Leitung direkt (ohne Angstwiderstand) mit dem AVR verbunden. Aufgrund der nicht zu verachtenden Kapazität des Breadboards un des Tastkopfes (Impedanz weiß ich gerade nicht auswendig) dürften die Messwerte deutlich verzerrt sein! Die Bilder und Erklärungen dienen daher höchstens zum Veranschaulichen des vorherigen Abschnitts! <gallery> Bild:Touchlight untouched.png|Unberührte Sensorfläche Bild:Touchlight touched.png|Berührte Sensorfläche Bild:Touchlight burst untuched.png|"Abfrageburst" unberührt Bild:Touchlight burst touched.png|"Abfrageburst" berührt </gallery> Im ersten Bild ist der Spannungsverlauf zu sehen, bei dem die Sensorfläche nicht berührt wurde. Entgegen der Datenblattangabe erkennt der AVR den High-Pegel bei 2,58V, wobei es 26,6µs dauert, bis dieser Wert erreicht wird. Wird die komplette Sensorfläche mit der Hand abgedeckt, steigt die Dauer bis zum Schwellenwert auf 41µs, also etwa das 1,5-fache der Zeit der unberührten Sensorfläche. Bei einem CPU-Takt von 9,6MHz sind dies 394 Taktzyklen (im Vergleich zu 256 Taktzyklen vorher), die man recht entspannt messen kann. In den letzten beiden Bildern ist ein kompletter "Abfrageburst" (5 Einzelabfragen) zu sehen. Auch wenn es auf den ersten Blick irreführend ist, die Bildunterschriften sind korrekt. Bei den beiden Fotos habe ich (dummerweise) eine andere Zeitbasis gewählt. Auch bei den Bursts hat das Zeitverhältnis zwischen unberührt und berührt den Faktor 1,5. Wobei ich dazu sagen muss: '''Traue keiner Statistik, die du nicht selbst gefälscht hast!''' Die gemessenen Dauern schwanken insbesondere beim Berühren der Sensorfläche immens. Hauptursache dürfte wahrscheinlich der Elektrosmog sein, der die 50 bzw. 100Hz (Halbwellen) aus dem Stromnetz beisteuert... = Die Software = Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <pre> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~pin; //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & pin) && --sampletime); //Zeit messen KEYDDR |= pin; //Pin als Ausgang -> entladen return sampletime; } </pre> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <pre> ... i = 0; n = 6; while(--n) { i += getcap(1<<PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </pre> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <pre> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </pre> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. == Download == [[Datei:Touch_1.0.zip]] Enthält sowohl den simplen Touchsensor als auch die Version mit serieller Ausgabe. CPU-Takt muss jeweils 9,6MHz sein (Bei Fabrikneuen Tiny13ern muss die CKDIV8-Fuse entfernt werden, damit das Teil bei vollem Takt läuft), der Rest nach eigenem Ermessen. Stromlaufpläne ist bei beiden Sourcen gleich, bei TouchSense ist zusätzlich der (nicht-invertierte) UART auf PBO. Dort werden die Messwerte der beiden Sensoren Tab-getrennt ausgegeben. die Konstante MINDELAY für den UART-Pause in suart.c muss wahrscheinlich angepasst werden. [[Category:AVR]] fe7914255d415d464454ca5b2f46f1ff1073886a 427 424 2010-06-13T09:34:30Z Chris 2 /* Leuchtmittel */ Tippfehler, Formulierung wikitext text/x-wiki Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. = Leuchtmittel = Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "ultrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos selektieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen, der über zwei Hardware-PWMs verfügt. Um diese auch nutzen zu können, wird die LED-Leiste in zwei Stränge unterteilt. Die Anzahl der LEDs wird einzig durch das Netzteil beschränkt (ein austemustertes SonyEricsson-Ladegerät). Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. = Bedienung = Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. [Kategorie:AVR] Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. = Theorie = [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> U(t) = U0*(1-e^(-t/(R*C)) Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. = Praxis = Um es noch ein wenig anschaulicher zu machen, habe ich das Oszilloskop auf die Schaltung angesetzt. Dazu wurde die Schaltung auf dem Breadboard aufgebaut. Die Ladewiderstände entsprechen wie im Schaltplan 1,1MOhm. Die Sensorfläche mit 28x28mm (7,8 cm²) und 1,5mm Dicke (Dielektrikum: Hartpapier) ist mit 5cm Leitung direkt (ohne Angstwiderstand) mit dem AVR verbunden. Aufgrund der nicht zu verachtenden Kapazität des Breadboards un des Tastkopfes (Impedanz weiß ich gerade nicht auswendig) dürften die Messwerte deutlich verzerrt sein! Die Bilder und Erklärungen dienen daher höchstens zum Veranschaulichen des vorherigen Abschnitts! <gallery> Bild:Touchlight untouched.png|Unberührte Sensorfläche Bild:Touchlight touched.png|Berührte Sensorfläche Bild:Touchlight burst untuched.png|"Abfrageburst" unberührt Bild:Touchlight burst touched.png|"Abfrageburst" berührt </gallery> Im ersten Bild ist der Spannungsverlauf zu sehen, bei dem die Sensorfläche nicht berührt wurde. Entgegen der Datenblattangabe erkennt der AVR den High-Pegel bei 2,58V, wobei es 26,6µs dauert, bis dieser Wert erreicht wird. Wird die komplette Sensorfläche mit der Hand abgedeckt, steigt die Dauer bis zum Schwellenwert auf 41µs, also etwa das 1,5-fache der Zeit der unberührten Sensorfläche. Bei einem CPU-Takt von 9,6MHz sind dies 394 Taktzyklen (im Vergleich zu 256 Taktzyklen vorher), die man recht entspannt messen kann. In den letzten beiden Bildern ist ein kompletter "Abfrageburst" (5 Einzelabfragen) zu sehen. Auch wenn es auf den ersten Blick irreführend ist, die Bildunterschriften sind korrekt. Bei den beiden Fotos habe ich (dummerweise) eine andere Zeitbasis gewählt. Auch bei den Bursts hat das Zeitverhältnis zwischen unberührt und berührt den Faktor 1,5. Wobei ich dazu sagen muss: '''Traue keiner Statistik, die du nicht selbst gefälscht hast!''' Die gemessenen Dauern schwanken insbesondere beim Berühren der Sensorfläche immens. Hauptursache dürfte wahrscheinlich der Elektrosmog sein, der die 50 bzw. 100Hz (Halbwellen) aus dem Stromnetz beisteuert... = Die Software = Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <pre> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~pin; //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & pin) && --sampletime); //Zeit messen KEYDDR |= pin; //Pin als Ausgang -> entladen return sampletime; } </pre> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <pre> ... i = 0; n = 6; while(--n) { i += getcap(1<<PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </pre> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <pre> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </pre> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. == Download == [[Datei:Touch_1.0.zip]] Enthält sowohl den simplen Touchsensor als auch die Version mit serieller Ausgabe. CPU-Takt muss jeweils 9,6MHz sein (Bei Fabrikneuen Tiny13ern muss die CKDIV8-Fuse entfernt werden, damit das Teil bei vollem Takt läuft), der Rest nach eigenem Ermessen. Stromlaufpläne ist bei beiden Sourcen gleich, bei TouchSense ist zusätzlich der (nicht-invertierte) UART auf PBO. Dort werden die Messwerte der beiden Sensoren Tab-getrennt ausgegeben. die Konstante MINDELAY für den UART-Pause in suart.c muss wahrscheinlich angepasst werden. [[Category:AVR]] 03401ec95a8ca2be42f99c1b919fc27a1b0de309 Datei:Xkcd.png 6 131 414 2010-05-30T15:23:58Z Chris 2 Testbild wikitext text/x-wiki Testbild d92bc2acff76a864a2fa3eb4edd0c4e11cfefd00 Testseite 0 2 415 16 2010-05-30T15:25:58Z Chris 2 gefällt mir ;) wikitext text/x-wiki Testseite, für interne Verwendung. [[Datei:Xkcd.png]] [[Datei:Xkcd.png|thumb]] [[Category:Elektronik]] 9075882d17de7d6a5b799fbf7eae73d4ed2e045e 432 415 2010-06-13T10:34:05Z Chris 2 wikitext text/x-wiki {{Infobox AVR | Typ = AtMega Schießmichtot | Takt = 42 | FuseH = 0xFF | FuseL = 0xFF | FuseE = 0xFF }} Testseite, für interne Verwendung. [[Datei:Xkcd.png]] [[Datei:Xkcd.png|thumb]] [[Category:Elektronik]] 74c5a25021f94c8a31aecba9ec05c5f131bb3446 435 432 2010-06-13T10:42:03Z Chris 2 wikitext text/x-wiki {{Infobox AVR | Typ = AtMega Schießmichtot | Takt = 42 | FuseH = 0xFF | FuseL = 0xFF }} Testseite, für interne Verwendung. [[Datei:Xkcd.png]] [[Datei:Xkcd.png|thumb]] [[Category:Elektronik]] 092b33d596c5504887e573056a6dde6decaa8910 Image Resizer 0 63 416 283 2010-06-02T11:55:04Z Chris 2 Download-Link korrigiert wikitext text/x-wiki ==Ausgangssituation== Eine Bekannte mit mäßigen Kenntnissen in Bildbearbeitung möchte in regelmäßigen Zeitabständen Bilder auf ihre Homepage hochladen. ==Problem== Die Bilder von der Digitalkamera sind groß und die Internetverbindung langsam. Also müssen sie in zwei Hinsichten verkleinert werden: Bildgröße und Dateigröße. ==Lösung== PHP war schon öfter der schnelle (und v.a. dreckige) Weg zum Erfolg. Also habe ich Teile meines schon etwas in die Tage gekommenen [http://hobbyelektronik.org/fotos Foto-Albums] verwertet und ein kleines Script erstellt, das die Arbeit übernimmt. Damit die gute Frau die Bilder nicht auf meinen Webserver hochladen muss um sie dann kleiner wieder zu bekommen (hirnrissig, siehe Problem), soll das ganze auf dem eigenen PC laufen - ohne Webserver. PHP bietet von sich aus ein CLI (Commandline-Interface) an, dafür braucht man allerdings trotzdem alle PHP-bezogenen Dateien. Ungut, weil man etwas falsch machen kann... Dank Bambalam und seinem Compiler/Embedder [http://www.bambalam.se/bamcompile/ Bamcompile] kann man aus PHP-Scripts selbstständig lauffähige EXE-Dateien erstellen - sogar mit Extensions! Also habe ich das Script etwas mehr auf CLI angepasst und mit Bamcompile zur Executable verarbeitet. ==Verwendung== Einfach Bilddateien (JPG, GIF, PNG) auf resize.exe ziehen und schon wird verkleinert. Die verkleinerten Bilder werden im gleichen Ordner erstellt und ihnen wird ein "_sm" angehängt, aus IMG_1234.JPG wird also IMG_1234_sm.JPG Achtung: bestehende Dateien mit diesem Namen werden ohne Rückfrage überschrieben Momentan wird die lange Kante des Bildes auf 1600 Pixel verkleinert, das Seitenverhältnis bleibt gleich. Bei JPEG wird standardmäßig eine Qualitätsstufe von 90% verwendet. Beide Werte können in der resize.php ganz oben verändert werden, danach muss sie aber neu kompiliert werden. Ich habe einige Testbilder (ok, 10 Megapixel) um sage und schreibe 90% komprimieren können. ==Download== [[Datei:Resizepics.zip]] (1,2MB) Nach dem Download muss nur noch die ZIP dekomprimiert werden und einmal compile.bat ausgeführt werden (die EXE liegt aus Platzgründen nicht dabei, dafür der Compiler) [[Category:Software]] ed388f250cfad3b582f55d67f594fb5adc78ff46 417 416 2010-06-02T12:04:32Z Chris 2 Oops wikitext text/x-wiki ==Ausgangssituation== Eine Bekannte mit mäßigen Kenntnissen in Bildbearbeitung möchte in regelmäßigen Zeitabständen Bilder auf ihre Homepage hochladen. ==Problem== Die Bilder von der Digitalkamera sind groß und die Internetverbindung langsam. Also müssen sie in zwei Hinsichten verkleinert werden: Bildgröße und Dateigröße. ==Lösung== PHP war schon öfter der schnelle (und v.a. dreckige) Weg zum Erfolg. Also habe ich Teile meines schon etwas in die Tage gekommenen [http://hobbyelektronik.org/fotos Foto-Albums] verwertet und ein kleines Script erstellt, das die Arbeit übernimmt. Damit die gute Frau die Bilder nicht auf meinen Webserver hochladen muss um sie dann kleiner wieder zu bekommen (hirnrissig, siehe Problem), soll das ganze auf dem eigenen PC laufen - ohne Webserver. PHP bietet von sich aus ein CLI (Commandline-Interface) an, dafür braucht man allerdings trotzdem alle PHP-bezogenen Dateien. Ungut, weil man etwas falsch machen kann... Dank Bambalam und seinem Compiler/Embedder [http://www.bambalam.se/bamcompile/ Bamcompile] kann man aus PHP-Scripts selbstständig lauffähige EXE-Dateien erstellen - sogar mit Extensions! Also habe ich das Script etwas mehr auf CLI angepasst und mit Bamcompile zur Executable verarbeitet. ==Verwendung== Einfach Bilddateien (JPG, GIF, PNG) auf resize.exe ziehen und schon wird verkleinert. Die verkleinerten Bilder werden im gleichen Ordner erstellt und ihnen wird ein "_sm" angehängt, aus IMG_1234.JPG wird also IMG_1234_sm.JPG Achtung: bestehende Dateien mit diesem Namen werden ohne Rückfrage überschrieben Momentan wird die lange Kante des Bildes auf 1600 Pixel verkleinert, das Seitenverhältnis bleibt gleich. Bei JPEG wird standardmäßig eine Qualitätsstufe von 90% verwendet. Beide Werte können in der resize.php ganz oben verändert werden, danach muss sie aber neu kompiliert werden. Ich habe einige Testbilder (ok, 10 Megapixel) um sage und schreibe 90% komprimieren können. ==Download== <strike>[[Datei:Resizepics.zip]] (1,2MB)</strike> '''Die ZIP-Datei ist momentan korrupt, ich stelle sie sobald wie möglich wieder her.''' Nach dem Download muss nur noch die ZIP dekomprimiert werden und einmal compile.bat ausgeführt werden (die EXE liegt aus Platzgründen nicht dabei, dafür der Compiler) [[Category:Software]] 9254644e4a46bff947a855e0cd0c189b096b5b25 418 417 2010-06-07T18:16:03Z Chris 2 Download funktioniert wieder wikitext text/x-wiki ==Ausgangssituation== Eine Bekannte mit mäßigen Kenntnissen in Bildbearbeitung möchte in regelmäßigen Zeitabständen Bilder auf ihre Homepage hochladen. ==Problem== Die Bilder von der Digitalkamera sind groß und die Internetverbindung langsam. Also müssen sie in zwei Hinsichten verkleinert werden: Bildgröße und Dateigröße. ==Lösung== PHP war schon öfter der schnelle (und v.a. dreckige) Weg zum Erfolg. Also habe ich Teile meines schon etwas in die Tage gekommenen [http://hobbyelektronik.org/fotos Foto-Albums] verwertet und ein kleines Script erstellt, das die Arbeit übernimmt. Damit die gute Frau die Bilder nicht auf meinen Webserver hochladen muss um sie dann kleiner wieder zu bekommen (hirnrissig, siehe Problem), soll das ganze auf dem eigenen PC laufen - ohne Webserver. PHP bietet von sich aus ein CLI (Commandline-Interface) an, dafür braucht man allerdings trotzdem alle PHP-bezogenen Dateien. Ungut, weil man etwas falsch machen kann... Dank Bambalam und seinem Compiler/Embedder [http://www.bambalam.se/bamcompile/ Bamcompile] kann man aus PHP-Scripts selbstständig lauffähige EXE-Dateien erstellen - sogar mit Extensions! Also habe ich das Script etwas mehr auf CLI angepasst und mit Bamcompile zur Executable verarbeitet. ==Verwendung== Einfach Bilddateien (JPG, GIF, PNG) auf resize.exe ziehen und schon wird verkleinert. Die verkleinerten Bilder werden im gleichen Ordner erstellt und ihnen wird ein "_sm" angehängt, aus IMG_1234.JPG wird also IMG_1234_sm.JPG Achtung: bestehende Dateien mit diesem Namen werden ohne Rückfrage überschrieben Momentan wird die lange Kante des Bildes auf 1600 Pixel verkleinert, das Seitenverhältnis bleibt gleich. Bei JPEG wird standardmäßig eine Qualitätsstufe von 90% verwendet. Beide Werte können in der resize.php ganz oben verändert werden, danach muss sie aber neu kompiliert werden. Ich habe einige Testbilder (ok, 10 Megapixel) um sage und schreibe 90% komprimieren können. ==Download== [[Datei:Resizepics.zip]] (1,2MB) Nach dem Download muss nur noch die ZIP dekomprimiert werden und einmal compile.bat ausgeführt werden (die EXE liegt aus Platzgründen nicht dabei, dafür der Compiler) [[Category:Software]] aeb5524180af5ede9d5bd68e74f60ea0dd00709c Datei:Touchlight untouched.png 6 132 419 2010-06-12T21:33:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Touchlight touched.png 6 133 420 2010-06-12T21:44:35Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Touchlight burst untuched.png 6 134 421 2010-06-12T21:45:00Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Touchlight burst touched.png 6 135 422 2010-06-12T21:45:27Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Vorlage:! 10 136 428 2010-06-13T10:20:44Z Chris 2 Für Infobox wikitext text/x-wiki | 3eb416223e9e69e6bb8ee19793911ad1ad2027d8 Vorlage:!! 10 137 429 2010-06-13T10:21:01Z Chris 2 Für Infobox wikitext text/x-wiki || c65f37b2cb1ae26c89e9b4f26e2ca9e9cde4ae5b Vorlage:Dokumentation 10 138 430 2010-06-13T10:31:32Z Chris 2 Öhm ja, versuch ists wert wikitext text/x-wiki <onlyinclude><hr class="rulerdocumentation hintergrundfarbe6" style="margin:1em 0.5em; height:0.7ex; " /> {{#ifeq:{{NAMESPACE}}|{{ns:0}}|<strong class="error">Achtung: Die {{Vorlage|Dokumentation}} wird im Artikelnamensraum verwendet. Wahrscheinlich fehlt <code>&lt;noinclude&gt;</code> in einer eingebundenen Vorlage oder die Kapselung ist fehlerhaft. Bitte {{Bearbeiten|text=entferne diesen Fehler}}.</strong>| <div id="framedocumentation"><div class="rahmenfarbe1" style="margin-bottom:0.5em; padding:0.5em; padding-top:0; clear:left; border-style:solid;" id="Vorlage_Dokumentation"> <div style="float:right; clear:left;">[[Datei:Information icon.svg|frameless|18px|link=#Dokumentation.Info|Informationen zu dieser Dokumentation|alt=]]</div> {{Überschriftensimulation 4|1=<span class="editsection">&#x5b;<span class="plainlinks">[{{fullurl:{{SUBJECTPAGENAME}}/Doku|action=edit}} Bearbeiten]</span>&#x5d;</span> Dokumentation}} {{#ifexist: {{SUBJECTPAGENAME}}/Doku| {{{{SUBJECTPAGENAME}}/Doku}} <br /><hr style="border:none; height:0.7ex; clear:both;" /> {{{!}} {{Bausteindesign5}} {{!}} Bei Fragen zu dieser [[Hilfe:Vorlagen|Vorlage]] kannst Du Dich an die [[Wikipedia:WikiProjekt Vorlagen/Werkstatt|Vorlagenwerkstatt]] wenden. {{!}}} {{{!}} cellspacing="8" cellpadding="0" class="plainlinks" style="background:transparent; margin: 2px 0;" id="Dokumentation.Info" {{!}} style="position:relative; width:35px; vertical-align:top;" {{!}} [[Datei:Information icon.svg|30px|Information|alt=]] {{!}} style="width: 100%;" {{!}} <ul> <li>{{#switch:{{ParmPart|1|{{{nr|<noinclude>10</noinclude>}}}}} | 1 = {{Verwendung|ns=1}} der Vorlage auf Artikel-Diskussionsseiten. | 2 = {{Verwendung|ns=2}} der Vorlage auf Benutzerseiten. | 3 = {{Verwendung|ns=3}} der Vorlage auf Benutzer-Diskussionsseiten. | 4 = {{Verwendung|ns=4}} der Vorlage auf Systemseiten. | 6 = {{Verwendung|ns=6}} der Vorlage bei Dateien. | 10 = {{Verwendung|ns=10}} der Vorlage auf Vorlagenseiten. | 11 = {{Verwendung|ns=10}} der Vorlage auf Vorlagen-Diskussionsseiten. | 14 = {{Verwendung|ns=14}} der Vorlage auf Kategorieseiten. | #default = {{Verwendung}} der Vorlage in Artikeln. }}</li> <li>{{#switch:{{ParmPart|2|{{{nr|<noinclude>10</noinclude>}}}}} | 1 = {{Verwendung|ns=1}} der Vorlage auf Artikel-Diskussionsseiten. | 2 = {{Verwendung|ns=2}} der Vorlage auf Benutzerseiten. | 3 = {{Verwendung|ns=3}} der Vorlage auf Benutzer-Diskussionsseiten. | 4 = {{Verwendung|ns=4}} der Vorlage auf Systemseiten. | 6 = {{Verwendung|ns=6}} der Vorlage bei Dateien. | 10 = {{Verwendung|ns=10}} der Vorlage auf Vorlagenseiten. | 11 = {{Verwendung|ns=10}} der Vorlage auf Vorlagen-Diskussionsseiten. | 14 = {{Verwendung|ns=14}} der Vorlage auf Kategorieseiten. }}</li> <li> Diese Dokumentation befindet sich [[{{SUBJECTPAGENAME}}/Doku|auf einer eingebundenen Unterseite]].</li> {{#ifexist:{{SUBJECTPAGENAME}}/Wartung | <li>Für diese Vorlage existiert eine [[{{SUBJECTPAGENAME}}/Wartung|Wartungsseite]] zum Auffinden fehlerhafter Verwendungen.</li> | <li class="metadata metadata-label">[{{fullurl:{{SUBJECTPAGENAME}}/Wartung|action=edit&preload=Vorlage:Dokumentation/preload-wartung}} Wartungsseite erstellen].</li> }} {{#ifexist:{{SUBJECTPAGENAME}}/XML | <li>Für diese Vorlage existiert eine [[{{SUBJECTPAGENAME}}/XML|XML-Beschreibung]] für den [[Wikipedia:Helferlein/Vorlagen-Meister|Vorlagenmeister]].</li> | <li class="metadata metadata-label">[[tools:~revolus/Template-Master/index.de.html|XML-Beschreibungsseite erstellen]]</li> }} {{#ifexist:{{SUBJECTPAGENAME}}/Test | <li>Anwendungsbeispiele und Funktionalitätsprüfungen befinden sich auf der [[{{SUBJECTPAGENAME}}/Test|Testseite]].</li> | <li class="metadata metadata-label">[{{fullurl:{{SUBJECTPAGENAME}}/Test|action=edit&preload=Vorlage:Dokumentation/preload-test}} Test-/Beispielseite erstellen].</li> }} {{#ifexist:{{SUBJECTPAGENAME}}/Druck | <li>Es existiert eine spezielle [[{{SUBJECTPAGENAME}}/Druck|Druckversion]] für die [[Hilfe:Buchfunktion|Buchfunktion]].</li> | <li class="metadata metadata-label">[{{fullurl:{{SUBJECTPAGENAME}}/Druck|action=edit&preload=Vorlage:Dokumentation/preload-druck}} Druckversion erstellen].</li> }} {{#ifexist: {{SUBJECTPAGENAME}}/Meta | <li>Die Metadaten ([[Hilfe:Kategorien|Kategorien]] und [[Hilfe:Internationalisierung|Interwikis]]) {{#ifeq:{{NAMESPACE}}|{{ns:2}} | in [[{{SUBJECTPAGENAME}}/Meta]] werden '''nicht''' eingebunden, weil sich die Vorlage im [[Hilfe:Benutzernamensraum|Benutzernamensraum]] befindet | werden [[{{SUBJECTPAGENAME}}/Meta|von einer Unterseite eingebunden]] }}.</li> | <li class="metadata metadata-label">[{{fullurl:{{SUBJECTPAGENAME}}/Meta|action=edit&preload=Vorlage:Dokumentation/preload-meta}} Metadatenseite erstellen].</li> }} {{#ifexist:{{SUBJECTPAGENAME}}/Editnotice | <li>Es existiert eine [[{{SUBJECTPAGENAME}}/Editnotice|Editnotice]], die beim Bearbeiten angezeigt wird.</li> | <li class="metadata metadata-label">[{{fullurl:{{SUBJECTPAGENAME}}/Editnotice|action=edit&preload=Vorlage:Dokumentation/preload-editnotice}} Editnotice erstellen].</li> }} <li>[[Spezial:Präfixindex/{{SUBJECTPAGENAME}}/|Liste der Unterseiten]].</li> </ul> {{!}}} |<span class="plainlinks" style="font-size:150%;"> * [{{fullurl:{{SUBJECTPAGENAME}}/Doku|action=edit&preload=Vorlage:Dokumentation/preload-doku}} Dokumentation erstellen] {{#ifexist:{{SUBJECTPAGENAME}}/Meta|| * [{{fullurl:{{SUBJECTPAGENAME}}/Meta|action=edit&preload=Vorlage:Dokumentation/preload-meta}} Metadatenseite erstellen]}} {{#ifexist:{{SUBJECTPAGENAME}}/Test|| * [{{fullurl:{{SUBJECTPAGENAME}}/Test|action=edit&preload=Vorlage:Dokumentation/preload-test}} Test-/Beispielseite erstellen]}} {{#ifexist:{{SUBJECTPAGENAME}}/Wartung|| * [{{fullurl:{{SUBJECTPAGENAME}}/Wartung|action=edit&preload=Vorlage:Dokumentation/preload-wartung}} Wartungsseite erstellen]}} </span>{{#ifeq:{{NAMESPACE}}|{{ns:10}}| [[Kategorie:Vorlage:nicht dokumentiert|{{PAGENAME}}]] }} }} <div style="clear:both;" /> </div></div>{{#ifeq:{{NAMESPACE}}|{{ns:2}}||{{#ifexist: {{SUBJECTPAGENAME}}/Meta|{{{{SUBJECTPAGENAME}}/Meta}} }}}} }}<hr class="rulerdocumentation hintergrundfarbe6" style="margin:1em 0.5em; height:0.7ex; " /></onlyinclude> 1f4f8ef44d55b2468a2cbce6190bc66e5a1344e7 Vorlage:Infobox AVR 10 139 431 2010-06-13T10:32:34Z Chris 2 Erster Versuch... wikitext text/x-wiki <onlyinclude>{| class="float-right wikitable infobox" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || {{{FuseH}}} |- | Low || {{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} {{{FuseE}}} }} |}</onlyinclude> <pre><nowiki> {{Infobox AVR | Typ = | Takt = | FuseH = | FuseL = | FuseE = }} </nowiki></pre> 0692cd73c7fc8b0b3d06441548b16f93a3de0286 433 431 2010-06-13T10:35:20Z Chris 2 wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || {{{FuseH}}} |- | Low || {{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} {{{FuseE}}} }} |}</onlyinclude> f36b5e38b01a55d5ee779b2bdcfa3808feabd10f 438 433 2010-06-13T11:31:11Z Chris 2 Änderung 433 von [[Special:Contributions/Chris|Chris]] ([[User talk:Chris|Diskussion]]) wurde rückgängig gemacht. wikitext text/x-wiki <onlyinclude>{| class="float-right wikitable infobox" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || {{{FuseH}}} |- | Low || {{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} {{{FuseE}}} }} |}</onlyinclude> <pre><nowiki> {{Infobox AVR | Typ = | Takt = | FuseH = | FuseL = | FuseE = }} </nowiki></pre> 0692cd73c7fc8b0b3d06441548b16f93a3de0286 439 438 2010-06-13T11:31:46Z Chris 2 Änderung 438 von [[Special:Contributions/Chris|Chris]] ([[User talk:Chris|Diskussion]]) wurde rückgängig gemacht. wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || {{{FuseH}}} |- | Low || {{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} {{{FuseE}}} }} |}</onlyinclude> f36b5e38b01a55d5ee779b2bdcfa3808feabd10f 440 439 2010-06-13T11:35:52Z Chris 2 wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || {{{FuseH}}} |- | Low || {{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} {{{FuseE}}} }} |} [[Kategorie:AVR]] </onlyinclude> 313c3edc493ba698eebd9b85dceaee50b81d9a8b 442 440 2010-06-13T11:40:36Z Chris 2 Auto-Kategorie korrigiert wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || {{{FuseH}}} |- | Low || {{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} {{{FuseE}}} }} |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:Irgendwas]]}} </onlyinclude> d1091a0def1b1bbd799356aa643dd12297ac2b84 443 442 2010-06-13T11:41:27Z Chris 2 Auto-Kategorie korrigiert wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || {{{FuseH}}} |- | Low || {{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} {{{FuseE}}} }} |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:AVR]]}} </onlyinclude> 08be5ff97b755d1fc38ab717aca9a259b9d7eb0a Vorlage:Infobox AVR/Doku 10 140 434 2010-06-13T10:35:36Z Chris 2 Die Seite wurde neu angelegt: „ <pre><nowiki> {{Infobox AVR | Typ = | Takt = | FuseH = | FuseL = | FuseE = }} </nowiki></pre>“ wikitext text/x-wiki <pre><nowiki> {{Infobox AVR | Typ = | Takt = | FuseH = | FuseL = | FuseE = }} </nowiki></pre> d0c8bd1dd00b59235999d5bbbc779dff0fa7a15e 437 434 2010-06-13T11:30:44Z Chris 2 Die Seite wurde geleert. wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 441 437 2010-06-13T11:36:36Z Chris 2 Änderung 437 von [[Special:Contributions/Chris|Chris]] ([[User talk:Chris|Diskussion]]) wurde rückgängig gemacht. wikitext text/x-wiki <pre><nowiki> {{Infobox AVR | Typ = | Takt = | FuseH = | FuseL = | FuseE = }} </nowiki></pre> 61260f1903bb6848af7e53dedc39710b83bd75c5 MediaWiki:Common.css 8 141 436 2010-06-13T11:03:47Z Qsysopr 1 Einfach mal von Wikipedia geschnackt css text/css /* <source lang="css"> */ /*-----------------------------------------------------------------------------------------------*/ /* ACHTUNG! Common.css enthält die gemeinsamen Skin-Anpassungen der deutschsprachigen Wikipedia */ /*---------------------------------------------------------------------------------------------*/ /* Common.css ist in drei grundlegende Abschnitte gegliedert: */ /* 1. Editierbare Seiteninhalte */ /* 2. Sonstige Anpassungen (Spezialseiten, u.a.) */ /* 3. Hauptseitenspezifisches */ /* Jede Ergänzung/Änderung muss vorher jeweils für alle Skins auf Tauglichkeit getestet werden, */ /* individuell per User.css! Ist hier erstmal geändert, dauert es dank Cache eine Weile, bis die */ /* Änderungen bei allen Nutzern sichtbar oder, bei Fehlern, korrigiert sind. */ /* +++++ 1. ANPASSUNGEN DER ANZEIGE VON EDITIERBAREN SEITENINHALTEN +++++ */ /* Personennamen in Kapitälchen: class="Person" */ .Person { display: inline; font-variant: small-caps; font-style: normal; } /* [[Wikipedia:Zitate|Zitate]] (siehe [[Vorlage:Zitat]]) */ p.Zitat { font-style: normal; margin-bottom: 0; } p.cite { margin-top: 0; padding-left: 1em; } /* [[Wikipedia:Quellenangaben|Quellenangaben]] nicht kursiv, da sie ggf. verschiedene Bestandteile enthalten */ cite { font-style: normal; } /* Stylesheet-Ergänzung zu Standard-[[Wikipedia:Navigationsleisten|Navigationsleisten]] */ div.BoxenVerschmelzen, div.NavFrame { margin: 1.5em 0 0; padding: 2px; border: 1px solid #aaaaaa; text-align: center; border-collapse: collapse; font-size: 95%; clear: both; } div.BoxenVerschmelzen div.NavFrame, div.NavFrame + div.NavFrame { margin-top: 0; } div.BoxenVerschmelzen div.NavFrame { border-style: none; border-style: hidden; } div.NavFrame + div.NavFrame { border-top-style: none; border-top-style: hidden; } div.NavPic { margin: 0; padding: 2px; float: left; } div.NavFrame div.NavHead { font-weight: bold; font-size: 100%; background-color: #efefef; } div.NavFrame p, div.NavFrame div.NavContent, div.NavFrame div.NavContent p { font-size: 100%; } div.NavEnd { margin: 0; padding: 0; line-height: 1px; clear: both; } /* Stylesheet fuer den 'Ausklappen'-Button an Navileisten, der in [[MediaWiki:Common.js]] implementiert wird */ .NavToggle { font-size: x-small; float: right; } /* Workaround für Internet Explorer 6 */ div.NavFrame, div.NavPic, .NavToggle { position: relative; } /* Stylesheet-Ergänzung zu SideBoxen (ehedem [[Wikipedia:TownBox|TownBox]]) */ div.sideBox { position: relative; float: right; background: white; margin-left: 1em; border: 1px solid gray; padding: 0.3em; width: 200px; overflow: hidden; clear: right; } div.sideBox dl { padding: 0; margin: 0 0 0.3em 0; font-size: 96%; } div.sideBox dl dt { background: none; margin: 0.4em 0 0 0; } div.sideBox dl dd { margin: 0.1em 0 0 1.1em; background-color: #f3f3f3; } /* Stylesheet-Ergänzung zu [[Wikipedia:Taxoboxen|Taxoboxen]] und [[Wikipedia:Paläoboxen|Paläoboxen]] */ table.taxobox, table.palaeobox { border-collapse: collapse; border: 1px solid gray; float: right; clear: right; margin-left: 0.5em; background-color: white; } table.taxobox th { background-color: #9bcd9b; } table.palaeobox th { background-color: #e7dcc3; } table.taxobox th, table.palaeobox th { border: solid 1px gray; text-align: center; font-weight: bold; } table.taxobox td, table.palaeobox td { vertical-align: top; } table.taxobox .Person, table.palaeobox .Person { font-style: normal; } table.taxobox div.thumb, table.taxobox div.thumb * { background-color: #f9f9f9; } table.taxobox div.thumb, table.taxobox div.thumb *, table.palaeobox div.thumb, table.palaeobox div.thumb * { margin: 0 auto; padding: 0; float: none; border: none; } table.taxobox div.magnify, table.palaeobox div.magnify { display: none; } table.taxobox tr td div.thumb div div.thumbcaption { text-align: center; } table.palaeobox tr td div.thumb div div.thumbcaption { text-align: left; } table.taxobox td.Person, table.palaeobox td.Person { text-align: center; display: block; } table.taxobox td.taxo-name, table.taxobox td.taxo-bild, table.palaeobox td.taxo-name, table.palaeobox td.taxo-bild, table.palaeobox td.taxo-zeit { text-align: center; } table.palaeobox td.taxo-ort { text-align: left; } /* aus Vorlage zur Entlastung, skinabhängigen Darstellung und Kombinierbarkeit hierher ausgelagert */ .wikitable, .prettytable { margin: 1em 1em 1em 0; background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse; } .prettytable th, .prettytable td { border: 1px #aaa solid; padding: 0.2em; } .prettytable th { text-align: center; } .prettytable caption { font-weight: bold; } /* Zebra-Tabellen */ table.wikitable.zebra tr:nth-child(even) { background: white; } .nogrid th, .nogrid td { border: none; } div.float-left, table.float-left, .float-left { float: left; clear: left; } div.float-right, table.float-right, .float-right { float: right; clear: right; margin: 1em 0 1em 1em; } div.centered, table.centered, .centered { margin-left: auto; margin-right: auto; } .toptextcells td { vertical-align: top; } /* Bitte KEINE weiteren Definitionen dieser Art für Boxen hier, das gehört in entsprechende Vorlagen! */ /* Hier 20 Mal Trivialitäten wie "text-align:center" zu definieren verlangsamt alles und ist nicht */ /* Sinn der Sache. (Und wer nicht weiß warum, hat's nicht verstanden.) */ /* Do not expand [[Wikipedia:WikiProjekt Georeferenzierung|kvaleberg.com-URLs]] for printing */ #content span.coordinates a.external.text:after, #content span.coordinates a.external.autonumber:after, #content div.coordinates a.external.text:after, #content div.coordinates a.external.autonumber:after { content: ""; } /* Do not expand URLs for printing */ #content span.plainlinks-print a.external.text:after, #content span.plainlinks-print a.external.autonumber:after, #content div.plainlinks-print a.external.text:after, #content div.plainlinks-print a.external.autonumber:after { content: ""; } /* Metadaten (bspw. [[Wikipedia:Personendaten|Personendaten]]) */ table.metadata { border: 1px solid #aaaaaa; display: none; } .metadata-label { color: #aaaaaa; } span.metadata, span.metadata-inline { display: none; } /* * Farbdefinitionen für Rahmen und Hintergründe von [[Wikipedia:Textbausteine|Textbausteinen]]. * Hier: Standardvorgaben für "dunkle Schrift auf hellem Grund". * Für Hell-auf-dunkel-Skins ([[MediaWiki:Amethyst.css|Amethyst]]) müssen dort entsprechende Definitionen * zusätzlich eingetragen werden! Anpassungen für andere Skins sind optional. * (Die Angaben der Rahmenstärke dienen der Bequemlichkeit, so dass man * für dünne Rahmen nur noch "border-style" angeben muss.) */ .rahmenfarbe1 { /* Wie Inhaltsverzeichnis */ border-color: #aaaaaa; border-width: 1px; } .rahmenfarbe2 { /* Unauffällig, geringer Kontrast */ border-color: #e9e9e9; border-width: 1px; } .rahmenfarbe3 { /* "Rot", auffällig */ border-color: #c00000; border-width: 1px; } .rahmenfarbe4 { /* Neutrale Farbe, deutlich */ border-color: #8888aa; border-width: 1px; } .rahmenfarbe5 { /* "Schwarz", hoher Kontrast */ border-color: #000000; border-width: 1px; } tr.hintergrundfarbe1 th, tr th.hintergrundfarbe1, table.hintergrundfarbe1, .hintergrundfarbe1 { /* Wie Inhaltsverzeichnis */ background-color: #f9f9f9; } tr.hintergrundfarbe2 th, tr th.hintergrundfarbe2, table.hintergrundfarbe2, .hintergrundfarbe2 { /* "Weiß", für Nicht-Artikel-Seiten, neutral */ background-color: #ffffff; } tr.hintergrundfarbe3 th, tr th.hintergrundfarbe3, table.hintergrundfarbe3, .hintergrundfarbe3 { /* "Gelb", auffällig */ background-color: #ffff40; } tr.hintergrundfarbe4 th, tr th.hintergrundfarbe4, table.hintergrundfarbe4, .hintergrundfarbe4 { /* Sehr auffällig */ background-color: #ffaa00; } tr.hintergrundfarbe5 th, tr th.hintergrundfarbe5, table.hintergrundfarbe5, .hintergrundfarbe5 { /* Neutral, abgesetzt */ background-color: #e0e0e0; } tr.hintergrundfarbe6 th, tr th.hintergrundfarbe6, table.hintergrundfarbe6, .hintergrundfarbe6 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b3b7ff; } tr.hintergrundfarbe7 th, tr th.hintergrundfarbe7, table.hintergrundfarbe7, .hintergrundfarbe7 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffcbcb; } tr.hintergrundfarbe8 th, tr th.hintergrundfarbe8, table.hintergrundfarbe8, .hintergrundfarbe8 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffebad; } tr.hintergrundfarbe9 th, tr th.hintergrundfarbe9, table.hintergrundfarbe9, .hintergrundfarbe9 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b9ffc5; } /* Keine Vergrößerung der Zeilenhöhe durch hochgestellte Zahlen der Fußnoten */ sup.reference { font-weight: 400; font-style: normal; } sup, sub { line-height: 1em; } /* Hervorhebung der angeklickten Fußnoten und der Rückverweise in blau */ ol.references > li:target, sup.reference:target { background-color: #def; } /* Hochgestellte Buchstaben in der Einzelnachweiseliste kursiv setzen */ ol.references li a[href|="#cite_ref"] { font-style: italic; } /* Inline-Verwendung der [[:Kategorie:Vorlage:Schwesterprojektverweis|Schwesterprojektverweise]] */ ol.references li div.sisterproject { display: inline !important; } /* Für <nowiki><hiero>…</hiero></nowiki> */ .mw-hierotable, .mw-hierotable th, .mw-hierotable td { border: 0; padding: 0; } /* Für [[MediaWiki:Anoneditwarning]] und weitere Hinweise, die alle untereinander stehen */ #mw-anon-edit-warning, #mw-missingsummary, #wp_talkpagetext { width: 80%; background: #d3e1f2; border: 1px solid #1a47ff; margin: 1em auto; padding: 1em; } /* Bei URLs, die auf unser Projekt und verwandte Projekte verweisen, den Pfeil ausblenden * Dieser Pfeil dient nur dazu, auf externe Ziele hinzuweisen * Auf den Einsatz der Klasse "plainlinks" kann dadurch verzichtet werden */ #content a[href^="http://de.wikipedia.org"], #content a[href^="http://toolserver.org"] { background: none !important; padding-right: 0 !important; } #content .mw-search-formheader div.search-types ul li a[href^="http://de.wikipedia.org"], #content .mw-search-formheader div.search-types ul li a[href^="http://toolserver.org"] { padding-right: 0.5em !important; } /* Falls bei der Seitenbearbeitung vergessen wurde, die Zusammenfassung auszufüllen */ .mw-summarymissed { border: 5px solid red; padding: 2px; } /* Copyrightwarnung */ #editpage-copywarn { border: solid 1px #c00000; font-size: 90%; background-color: #ffffff; } .mw-tos-summary { border: solid 1px #c00000; background-color: #ffffff; padding-left: 1em; } /* +++++ 2. SONSTIGE ANPASSUNGEN (Spezialseiten u. a.) +++++ */ /* Markierung von Redirects in [[Special:Allpages]], [[Special:Watchlist]], Kategorien */ .allpagesredirect, .watchlistredir, .redirect-in-category { font-style: italic; } /* Fettformatierung von Admin-Spezialseiten in [[Special:Specialpages]] abschalten */ .mw-specialpagerestricted strong { font-weight: normal; } /* Legende auf [[Special:Specialpages]] ebenfalls abschalten */ div.mw-specialpages-notes { display: none; } /* Größerer Abstand zwischen TOC-Nummerierung und TOC-Eintrag */ span.tocnumber { margin-right: 0.3em; } /* Skinabhängige absolute Positionierungen ausblenden */ /* Bitte [[MediaWiki Diskussion:Common.css#Absolute_Positionierungen]] beachten */ #coordinates, #coordinates_3_ObenRechts, #issnlink, #editcount, #shortcut, #artikelstadium, .topicon, #spoken-icon, #commons-icon { display: none; } /* Anpassungen für [[:Template:Link_FA]] */ /* hide the template */ #bodyContent span.FA { display: none; } /* change the bullets for links to special articles */ #p-lang li.FA { /* hier immer auch linkFA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/d/d0/Monobook-bullet-star-transparent.png"); } /* change the bullets for links to special articles */ #p-lang li.GA { /* hier immer auch linkGA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/a/a1/Monobook-bullet-star-gray.png"); } /* Verhindere, dass Infoboxen etc. in den Inhalt von Kategorien hineinragen. Das betrifft nur Kategorieseiten. */ #mw-subcategories, #mw-pages { clear: both; } /* DIVs in ImageMaps inlinen (Vorschlag von Revolus) */ .imagemap-inline div { display: inline; } /* [[Special:Hochladen]]: Warnmeldung auf bestehende Dateien, unerwünschte Prefixe usw. deutlicher hervorheben. */ #wpDestFile-warning ul { border: solid red 1px; padding: 1.5em; } /* Warnmeldung für gesperrte Titel */ .mw-titleprotectedwarning { background-color: #eee; border: 2px solid red; padding: 1em; } /* Warnmeldung bei der Bearbeitung von Seiten im MediaWiki-Namensraum */ .mw-editinginterface { background-color: #f9f9f9; border-color: #c00000; border-width: 1px; border-style: solid; padding: 2px; } /* Überschrift 5. und 6. Ordnung proportionaler zu Fließtext */ #content h5 { font-size: 108%; /* Original: 116% */ } #content h6 { font-size: 100%; /* Original: 80% = kleiner als Bodytext, unschön */ } #content h6 .editsection { font-size: 120%; font-weight: normal; } /* Anleitung auf Special:Search */ .mw-searchresult { font-size: 84%; margin: 5px; } /* Gestaltung der Edittools-Leiste */ #specialchars { margin-top: 3px; border: solid 1px #aaaaaa; padding: 1px; text-align: left; background-color: white; } /* Legende für Versionsgeschichte */ .mw-history-legend { font-size: 90%; margin-top: 2px; margin-bottom: 2px; border: solid 1px #e9e9e9; padding: 0 5px 5px 5px; background-color: #f9f9f9; clear: both; } /* +++++ 3. NEUE [[Wikipedia:Hauptseite|HAUPTSEITE]] (ab 2006) +++++ */ /* Kategorie verbergen */ /* Überschrift verbergen */ /* Redirhinweis verbergen - ACHTUNG: Je nach Skin muss jetzt der Abstand zum oberen Rand korrigiert werden */ body.page-Wikipedia_Hauptseite #catlinks, body.page-Wikipedia_Hauptseite h1.firstHeading, body.page-Wikipedia_Hauptseite #contentSub { display: none; } #hauptseite h2 { background-color: #d8e8ff; border: 1px solid #8898bf; font-size: 1em; font-weight: bold; margin-top: 0; margin-bottom: 0; padding-top: 0.1em; padding-bottom: 0.1em; } #hauptseite .inhalt { background-color: #ffffff; border: 1px solid #8898bf; border-top: 0 solid white; padding: 0.3em 0.8em 0.4em 0.8em; } #hauptseite .inhalt hr { background-color: #8898bf; color: #8898bf; height: 1px; margin: 0.5em 0; padding: 0; } #hauptseite .inhalt .mehr { clear: both; font-size: 95%; margin-top: 0.8em; text-align: right; } #hauptseite table { background-color: transparent; } .hauptseite-oben, .hauptseite-links, .hauptseite-rechts { margin-bottom: 1em; } .hauptseite-links { margin-right: 0.5em; } .hauptseite-rechts { margin-left: 0.5em; } .hauptseite-oben h2, .hauptseite-unten h2 { text-align: center; } .hauptseite-oben .inhalt .portale { font-weight: bold; margin-top: 0.2em; margin-bottom: 0.2em; } .hauptseite-oben .inhalt .intern { font-size: 90%; text-align: center; } .hauptseite-links h2, .hauptseite-rechts h2 { text-indent: 0.8em; } #hauptseite-schwesterprojekte .inhalt a { font-weight: bold; } /* IPA links nicht unterstreichen */ .IPA a:link, .IPA a:visited { text-decoration: none; } /* CSS-Klassen für Schriftarten als Workaround für Defizite in alten IE-Versionen. * Achtung: IE6 mag keine Zeilenumbrüche zwischen den Fonts. * In IE8 nicht mehr nötig, soll mit den alten Versionen aussterben. Browserweiche: * http://www.dynamicsitesolutions.com/css/filters/star-html/ * http://www.dynamicsitesolutions.com/css/filters/first-child-plus-html/ */ * html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } *:first-child+html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } * html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } *:first-child+html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } * html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } *:first-child+html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } * html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } *:first-child+html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } * html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } *:first-child+html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } * html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } *:first-child+html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } * html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } *:first-child+html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } * html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } *:first-child+html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } * html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } *:first-child+html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } /* Standardmäßige Ausblendung der Flagged-Revisions-Backlog-Sitenotice */ #mw-oldreviewed-notice { display: none; } /* Standardmäßige Ausblendung der Flagged-Revisions-Kommentarbox */ #mw-commentbox { display: none; } /* Abstand zwischen Liste und Inhaltsverzeichnis erhöhen, siehe http://de.wikipedia.org/w/index.php?title=MediaWiki_Diskussion:Common.css&oldid=51639015#Abstand_vor_Inhaltsverzeichnis */ ul + .toc, ol + .toc { margin-top: 0.5em; } /* höheres Uploadfeld */ #wpUploadDescription { height: 20em; } /* Im Projekt WP:GEO benutzt die [[Vorlage:Coordinate]] das «geo-microformat» zur semantischen Auszeichnung des Texts. Der Inhalt dieses [[Tag (Informatik)|Tags]] ist nicht für den Leser bestimmt. */ .geo { display: none; } /* Patrollink ausblenden, da die Eweiterung hier nicht aktiviert ist und deren Optik zu sehr den gesichteten Versionen ähnelt. */ .fr-diff-patrollink, .patrollink { display: none; } /* Rollback-Knopf auf Beobachtungsliste ausblenden, da es dort nur von sehr beschränktem Nutzen ist und zu sehr vielen Reverts aus Versehen führt */ .page-Spezial_Beobachtungsliste .mw-rollback-link { display: none; } /* </source> */ fd037dda71821f351966ac7a1ebb1fab2b8bd387 AVR-Doper 0 44 446 341 2010-06-13T11:49:57Z Chris 2 Infobox AVR hinzugefügt wikitext text/x-wiki {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = 0xC9 | FuseL = 0x9F }} Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Ich habe auch damit angefangen, eine SMD-Version der Platine zu machen, allerdings gibt es ein paar Platzprobleme (der ATMega in TQFP ist einfach zu klein für die ganzen Bauteile außen herum). Die Firmware wurde nicht verändert und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download des optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] [[Category:AVR]] [[Category:USB]] [[Category:PC]] bc8d77f043732245ec36bbf6e8dbd4789da8045f Touchlight 0 92 447 427 2010-06-13T11:53:29Z Chris 2 Infobox AVR hinzugefügt wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny13 | Takt = 9,6 | FuseH = 0xFF | FuseL = 0x7A }} Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. = Leuchtmittel = Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "ultrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos selektieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen, der über zwei Hardware-PWMs verfügt. Um diese auch nutzen zu können, wird die LED-Leiste in zwei Stränge unterteilt. Die Anzahl der LEDs wird einzig durch das Netzteil beschränkt (ein austemustertes SonyEricsson-Ladegerät). Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. = Bedienung = Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. [Kategorie:AVR] Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. = Theorie = [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> U(t) = U0*(1-e^(-t/(R*C)) Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. = Praxis = Um es noch ein wenig anschaulicher zu machen, habe ich das Oszilloskop auf die Schaltung angesetzt. Dazu wurde die Schaltung auf dem Breadboard aufgebaut. Die Ladewiderstände entsprechen wie im Schaltplan 1,1MOhm. Die Sensorfläche mit 28x28mm (7,8 cm²) und 1,5mm Dicke (Dielektrikum: Hartpapier) ist mit 5cm Leitung direkt (ohne Angstwiderstand) mit dem AVR verbunden. Aufgrund der nicht zu verachtenden Kapazität des Breadboards un des Tastkopfes (Impedanz weiß ich gerade nicht auswendig) dürften die Messwerte deutlich verzerrt sein! Die Bilder und Erklärungen dienen daher höchstens zum Veranschaulichen des vorherigen Abschnitts! <gallery> Bild:Touchlight untouched.png|Unberührte Sensorfläche Bild:Touchlight touched.png|Berührte Sensorfläche Bild:Touchlight burst untuched.png|"Abfrageburst" unberührt Bild:Touchlight burst touched.png|"Abfrageburst" berührt </gallery> Im ersten Bild ist der Spannungsverlauf zu sehen, bei dem die Sensorfläche nicht berührt wurde. Entgegen der Datenblattangabe erkennt der AVR den High-Pegel bei 2,58V, wobei es 26,6µs dauert, bis dieser Wert erreicht wird. Wird die komplette Sensorfläche mit der Hand abgedeckt, steigt die Dauer bis zum Schwellenwert auf 41µs, also etwa das 1,5-fache der Zeit der unberührten Sensorfläche. Bei einem CPU-Takt von 9,6MHz sind dies 394 Taktzyklen (im Vergleich zu 256 Taktzyklen vorher), die man recht entspannt messen kann. In den letzten beiden Bildern ist ein kompletter "Abfrageburst" (5 Einzelabfragen) zu sehen. Auch wenn es auf den ersten Blick irreführend ist, die Bildunterschriften sind korrekt. Bei den beiden Fotos habe ich (dummerweise) eine andere Zeitbasis gewählt. Auch bei den Bursts hat das Zeitverhältnis zwischen unberührt und berührt den Faktor 1,5. Wobei ich dazu sagen muss: '''Traue keiner Statistik, die du nicht selbst gefälscht hast!''' Die gemessenen Dauern schwanken insbesondere beim Berühren der Sensorfläche immens. Hauptursache dürfte wahrscheinlich der Elektrosmog sein, der die 50 bzw. 100Hz (Halbwellen) aus dem Stromnetz beisteuert... = Die Software = Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <pre> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~pin; //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & pin) && --sampletime); //Zeit messen KEYDDR |= pin; //Pin als Ausgang -> entladen return sampletime; } </pre> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <pre> ... i = 0; n = 6; while(--n) { i += getcap(1<<PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </pre> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <pre> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </pre> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. == Download == [[Datei:Touch_1.0.zip]] Enthält sowohl den simplen Touchsensor als auch die Version mit serieller Ausgabe. CPU-Takt muss jeweils 9,6MHz sein (Bei Fabrikneuen Tiny13ern muss die CKDIV8-Fuse entfernt werden, damit das Teil bei vollem Takt läuft), der Rest nach eigenem Ermessen. Stromlaufpläne ist bei beiden Sourcen gleich, bei TouchSense ist zusätzlich der (nicht-invertierte) UART auf PBO. Dort werden die Messwerte der beiden Sensoren Tab-getrennt ausgegeben. die Konstante MINDELAY für den UART-Pause in suart.c muss wahrscheinlich angepasst werden. [[Category:AVR]] 36da285683b6be42be9c37659e3bf095a9304f2d 470 447 2010-07-08T19:03:01Z Chris 2 Fuses angepasst wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny13 | Takt = 9,6 | FuseH = FF | FuseL = 7A }} Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. = Leuchtmittel = Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "ultrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos selektieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen, der über zwei Hardware-PWMs verfügt. Um diese auch nutzen zu können, wird die LED-Leiste in zwei Stränge unterteilt. Die Anzahl der LEDs wird einzig durch das Netzteil beschränkt (ein austemustertes SonyEricsson-Ladegerät). Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. = Bedienung = Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. [Kategorie:AVR] Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. = Theorie = [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> U(t) = U0*(1-e^(-t/(R*C)) Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. = Praxis = Um es noch ein wenig anschaulicher zu machen, habe ich das Oszilloskop auf die Schaltung angesetzt. Dazu wurde die Schaltung auf dem Breadboard aufgebaut. Die Ladewiderstände entsprechen wie im Schaltplan 1,1MOhm. Die Sensorfläche mit 28x28mm (7,8 cm²) und 1,5mm Dicke (Dielektrikum: Hartpapier) ist mit 5cm Leitung direkt (ohne Angstwiderstand) mit dem AVR verbunden. Aufgrund der nicht zu verachtenden Kapazität des Breadboards un des Tastkopfes (Impedanz weiß ich gerade nicht auswendig) dürften die Messwerte deutlich verzerrt sein! Die Bilder und Erklärungen dienen daher höchstens zum Veranschaulichen des vorherigen Abschnitts! <gallery> Bild:Touchlight untouched.png|Unberührte Sensorfläche Bild:Touchlight touched.png|Berührte Sensorfläche Bild:Touchlight burst untuched.png|"Abfrageburst" unberührt Bild:Touchlight burst touched.png|"Abfrageburst" berührt </gallery> Im ersten Bild ist der Spannungsverlauf zu sehen, bei dem die Sensorfläche nicht berührt wurde. Entgegen der Datenblattangabe erkennt der AVR den High-Pegel bei 2,58V, wobei es 26,6µs dauert, bis dieser Wert erreicht wird. Wird die komplette Sensorfläche mit der Hand abgedeckt, steigt die Dauer bis zum Schwellenwert auf 41µs, also etwa das 1,5-fache der Zeit der unberührten Sensorfläche. Bei einem CPU-Takt von 9,6MHz sind dies 394 Taktzyklen (im Vergleich zu 256 Taktzyklen vorher), die man recht entspannt messen kann. In den letzten beiden Bildern ist ein kompletter "Abfrageburst" (5 Einzelabfragen) zu sehen. Auch wenn es auf den ersten Blick irreführend ist, die Bildunterschriften sind korrekt. Bei den beiden Fotos habe ich (dummerweise) eine andere Zeitbasis gewählt. Auch bei den Bursts hat das Zeitverhältnis zwischen unberührt und berührt den Faktor 1,5. Wobei ich dazu sagen muss: '''Traue keiner Statistik, die du nicht selbst gefälscht hast!''' Die gemessenen Dauern schwanken insbesondere beim Berühren der Sensorfläche immens. Hauptursache dürfte wahrscheinlich der Elektrosmog sein, der die 50 bzw. 100Hz (Halbwellen) aus dem Stromnetz beisteuert... = Die Software = Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <pre> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~pin; //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & pin) && --sampletime); //Zeit messen KEYDDR |= pin; //Pin als Ausgang -> entladen return sampletime; } </pre> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <pre> ... i = 0; n = 6; while(--n) { i += getcap(1<<PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </pre> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <pre> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </pre> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. == Download == [[Datei:Touch_1.0.zip]] Enthält sowohl den simplen Touchsensor als auch die Version mit serieller Ausgabe. CPU-Takt muss jeweils 9,6MHz sein (Bei Fabrikneuen Tiny13ern muss die CKDIV8-Fuse entfernt werden, damit das Teil bei vollem Takt läuft), der Rest nach eigenem Ermessen. Stromlaufpläne ist bei beiden Sourcen gleich, bei TouchSense ist zusätzlich der (nicht-invertierte) UART auf PBO. Dort werden die Messwerte der beiden Sensoren Tab-getrennt ausgegeben. die Konstante MINDELAY für den UART-Pause in suart.c muss wahrscheinlich angepasst werden. [[Category:AVR]] c19d9a57d40bbfa405deff62f347427c30f224b2 USBLotIO 0 95 448 387 2010-06-13T11:54:37Z Chris 2 Infobox AVR hinzugefügt wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = 0xDD | FuseL = 0xE1 | FuseE = 0xFF }} Die parallele Schnittstelle am PC ist tot. Nachdem sie schon vor einigen Jahren bei Notebooks verschwunden ist, findet man sie heute auch kaum noch bei Desktop-PCs. Selbst bei teureren Mainboards sind oft nur noch Pinheader vorhanden. Ein Slotblech dafür wird generell nicht geliefert. Die ganzen Drucker sind jetzt schneller und mit dünneren Leitungen per USB angebunden. Soweit, so gut. Nur wird die Luft für Bastler langsam dünner, wenn man keine größeren Ambitionen zu RS232 hat (deren Anschlüsse am PC auch langsam aussterben). Aus diesem Grund hatte ich die Idee, eine kleine Schaltung zu bauen, die zwar keinen Ersatz aber eine Alternative zum guten alten Parport darstellt. == Anforderungen == * Anbindung, die auch noch in ein paar Jahren funktioniert * Einfacher Aufbau * Einfach vom PC ansprechbar * Erweiterbar == Hardware == [[Bild:Usblotio_sch.png|thumb|Stromlaufplan der Platinen]] Die Anbindung an den PC findet per USB statt. Hier soll (wieder einmal) [http://www.obdev.at/products/vusb/index-de.html V-USB] zum Einsatz kommen. Davon gibt es zwar schon ein Referenzdesign ([http://www.obdev.at/products/vusb/powerswitch.html PowerSwitch]), dieses hat meiner Meinung ein paar Schwachstellen: * keine Erweiterbarkeit * Treiber erforderlich (laufen die vorhandenen überhaupt unter Win7?) * relativ großer Aufbau Diesen Schwächen möchte ich mit einem ATTiny45 entgegenwirken. Dieser ist schön klein und braucht dank PLL (und automatischer Taktkalibrierung per USB) keinen externen Quarz. Damit man keine Treiber braucht, soll er sich dem Computer gegenüber als HID (Human Interface Device) ausgeben. Bleibt nur noch eines: Mit der Anbindung am PC bleiben nur noch 4 Pins am Tiny über - einer davon ist der Reset-Eingang - wie soll man da großartig Ausgänge schalten können? Ganz zu schweigen von der angestrebten Erweiterbarkeit... Die Lösung hierfür ist einfach: der Mikrocontroller steuert Schieberegister an, die beliebig kaskadiert werden können. So kann man quasi beliebig viele Ausgänge an den AVR dengeln. Als Ausgabeschieberegister dienen 74xx595, welche einen Latch haben und die Datenleitungen in einem Rutsch aktualisiert werden können. Um Signale auch lesen zu können, kommen 74xx165 zum Einsatz. Zwar haben diese auch einen Latch, allerdings ist dieser (anders als beim 595) low-aktiv. Damit wird's mit 4 I/Os am AVR eng. Gut, die Strobe-Leitungen muss man trennen, Clock kann gemeinsam laufen, nur sind jetzt schon alle Pins belegt. Es ist zwar möglich, die Daten ins Register zu laden, aber was bringen die Daten, wenn man sie nicht lesen kann? Mit einem kleinen Trick kann man das aber bewältigen: Die Datenleitungen beider Richtungen auf einen I/O. Zum Schutz des Ausganges des Registers gibt es aber einen Reihenwiderstand. Zwischen dem Lesen und Schreiben muss die Datenleitung einfach nur noch als Eingang bzw. Ausgang geschaltet werden. <gallery> Bild:Usblotio_povray.jpg|Mit [http://www.povray.org/ POV-Ray] gerendertes Layout der Platinen Bild:Usblotio_main.jpg|Aufgebaute Hauptplatine des USBLotIO Bild:Usblotio out.jpg|Aufgebautes Ausgabemodul </gallery> Aber Vorsicht: dadurch, dass der Reset-Pin auch verwendet wird, kann der Mikrocontroller nur mit HVSP programmiert werden! (oder man lässt eine "Richtung" weg - noch ungetestet). <b style="color: red;">Ein Wort der Warnung sei noch angebracht:</b> Bei vielen PCs ist die USB-Schnittstelle NICHT abgesichert, bei einem Kurzschluss geht dann die komplette Leistung des Netzteils durch! Das kann zu zerstörten Leiterbahnen (sowohl am USB-Gerät als auch auf dem Mainboard) oder sogar Bränden führen! In der Firmware ist eine Stromaufnahme von 20mA angegeben, welche schon bei kleineren Aufbauten überschritten werden kann. Die Inbetriebnahme findet unter eigener Verantwortung statt! Rechnungen für neue Mainboards o.a. an mich werden mit Freude durch den Aktenvernichter gejagt. == Software == === AVR === Wie bereits erwähnt läuft auf dem AVR objective developments V-USB als HID. Grundlage für meine Implementierung war das "Datastore"-Beispiel, das zusätzlich um die automatische Kalibrierung der CPU-Frequenz erweitert wurde. Da die USB-Schnittstelle zwangsläufig auf einem Interrupt-Pin hängt, der gleichzeitig auch für SPI verantwortlich ist, müssen die Schieberegister mit einem wesentlich langsameren Soft-SPI angesprochen werden. Der USB-Client reagiert bei dem Beginn einer Übertragung mit einem Aufruf der Methode usbFunctionSetup. In ihr wird dann entschieden, ob es sich um einen Schreib- oder Lesevorgang handelt. Hier wird zum einen die Speicheradresse auf 0 gesetzt und beim Leseaufruf die Zustände der Registereingänge in den RAM geschrieben. Anschließend wird von V-USB usbFunctionWrite bzw. usbFunctionRead je nach Reportgröße mehrmals aufgerufen. Im Read wird einfach nur der Inhalt des RAMs an den PC übertragen, beim Schreiben wird zuerst die Variable (die gleiche wie beim Lesen) gefüllt und nach dem letzten Wert vom PC die Methode processCommand aufgerufen. Die übertragenen Werte werden in Anschlussreihenfolge aus Sicht der Hauptplatine angegeben. Gibt man z.B. 0x01 0x02 aus, wird am Ausgabemodul, das am nächsten zur Hauptplatine angeschlossen ist 0x01 ausgegeben, am "zweitnächsten" 0x02. Bei den Eingabemodulen verhält es sich genauso. Dort findet das eigentliche Schreiben auf die Register statt. Zusätzlich zum simplen Schreiben kann man den Controller mit ein paar Logikfunktionen beauftragen. Diese werden immer mit der letzten Ausgabe verarbeitet. Folgende Operationen sind möglich: * Überschreiben * OR * AND * XOR Zusätzlich kann man ein Flag zum Invertieren übergeben, dadurch werden die Funktionen NOR, NAND und XNOR sowie invertiertes Überschreiben ermöglicht. Mit einem weiteren Flag kann man die errechneten Werte ins EEProm des Controllers schreiben. Dadurch kann man direkt beim Einschalten der Hardware einen definierten Zustand ausgeben. Das einzige, das man in der Software noch anpassen muss, ist die Anzahl der jeweiligen Schieberegister. Oder einfach unverändert lassen - dann werden jeweils 8 Register angenommen. Diese Werte muss man nur anpassen, wenn man mehr als 8 Schieberegister verwendet oder mehr Performance (Auswirkung noch nicht geprüft) wünscht. Ferner kann man eine ID in den EEProm schreiben, um mehrere (256) Devices zu unterscheiden. Diese ID wird bei jedem Lese-Vorgang im untersten Byte des Reports zurückgegeben. [[Bild:Usblotio_fuses.png|thumb|Im AVR programmierte Fuses]] Damit man die Hardware vollständig genutzt werden kann, müssen die Fuses wie folgt programmiert werden (siehe auch Screenshot): * Extended: 0xFF * High: 0x75 * Low: 0xE1 SPIEN kann nur deaktiviert werden, wenn man per HVSP programmiert, RSTDISBL ''sollte'' eigentlich reichen, habe ich allerdings nicht ausprobiert ;-) === PC === Auf dem PC kann eigentlich alles werkeln, was auf die entsprechenden USB-APIs zugreifen kann. Ich beschränke mich auf Windows, die Portierung auf *nix/Mac/etc. sollte aber nicht allzu schwierig sein. Im Grunde muss man nicht viel machen, das Schwierigste dürfte wahrscheinlich das Finden des Devices sein. Ich habe im C#-Programm Teile aus der [http://www.brianpeek.com/blog/pages/wiimotelib.aspx WiimoteLib] von Brian Peek genommen. Ist das HID gefunden und ein Handler gesetzt, können mit HidD_SetFeature und -GetFeature Reports an den AVR gesendet oder von ihm angefordert werden. Wichtig ist hier eigentlich nur die Größe des übergebenen Arrays, bei falscher Länge kommt oft einfach nichts beim Device an! Man kann relativ viel Zeit damit verbringen, dort nach einem Fehler zu suchen, zumal sich ein vollbelegter Mikrocontroller (dessen UART man nicht verwenden kann) schlecht debuggen lässt. Zur Demonstration habe ich eine kleine Konsolen-Anwendung rund um die USBLotIO-Klasse geschrieben. Kann sein, dass ich die Klasse noch ein wenig umstrukturiere - die nullable Byte-Arrays gefallen mir nicht sonderlich. Im Ordner \csharp\USBlotIO\bin\Release\ befindet sich ein kleines Konsolenprogramm (USBlotIO.exe), mit dem man alle Features der Hardware testen/nutzen kann. Einfach einmal ohne Parameter starten, dann werden alle möglichen Aufrufe angezeigt (wem es beim Start per Doppelklick zu schnell geht: cmd starten und damit die Anwendung aufrufen). == Test == Die Hardwareinstallation ist im Baukastenprinzip. Module anstecken und per USB-Kabel mit dem PC verbinden. Nach wenigen Sekunden ist das Gerät bereit für die Verwendung. Leider konnte ich das Board für Eingabemodule nicht testen, da Reichelt keine 74xx165 in SMD hat. Auf dem Breadboard hat es funktioniert, dennoch gebe ich momentan keine 100%ige Garantie auf korrekte Funktion! Erfolgreich getestet wurde die C#-Anwendung bisher unter WinXP Pro SP3 sowie Windows 7. Für Vista brauche ich erst noch einen Probanden, Windows 2000 lasse ich außen vor (freue mich aber über Erfolgsmeldungen). == Download == [[Datei:Usblotio.zip]] Firmware, EAGLE-Dateien und C#-Testprogramm (VS2008, .NET 2.0) [[Category:AVR]] [[Category:USB]] [[Category:PC]] 6f728c7ba7b9107455666e8b8ac6ddbc2537f1c9 471 448 2010-07-08T19:03:22Z Chris 2 Fuses angepasst wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = 0xDD | FuseL = E1 | FuseE = FF }} Die parallele Schnittstelle am PC ist tot. Nachdem sie schon vor einigen Jahren bei Notebooks verschwunden ist, findet man sie heute auch kaum noch bei Desktop-PCs. Selbst bei teureren Mainboards sind oft nur noch Pinheader vorhanden. Ein Slotblech dafür wird generell nicht geliefert. Die ganzen Drucker sind jetzt schneller und mit dünneren Leitungen per USB angebunden. Soweit, so gut. Nur wird die Luft für Bastler langsam dünner, wenn man keine größeren Ambitionen zu RS232 hat (deren Anschlüsse am PC auch langsam aussterben). Aus diesem Grund hatte ich die Idee, eine kleine Schaltung zu bauen, die zwar keinen Ersatz aber eine Alternative zum guten alten Parport darstellt. == Anforderungen == * Anbindung, die auch noch in ein paar Jahren funktioniert * Einfacher Aufbau * Einfach vom PC ansprechbar * Erweiterbar == Hardware == [[Bild:Usblotio_sch.png|thumb|Stromlaufplan der Platinen]] Die Anbindung an den PC findet per USB statt. Hier soll (wieder einmal) [http://www.obdev.at/products/vusb/index-de.html V-USB] zum Einsatz kommen. Davon gibt es zwar schon ein Referenzdesign ([http://www.obdev.at/products/vusb/powerswitch.html PowerSwitch]), dieses hat meiner Meinung ein paar Schwachstellen: * keine Erweiterbarkeit * Treiber erforderlich (laufen die vorhandenen überhaupt unter Win7?) * relativ großer Aufbau Diesen Schwächen möchte ich mit einem ATTiny45 entgegenwirken. Dieser ist schön klein und braucht dank PLL (und automatischer Taktkalibrierung per USB) keinen externen Quarz. Damit man keine Treiber braucht, soll er sich dem Computer gegenüber als HID (Human Interface Device) ausgeben. Bleibt nur noch eines: Mit der Anbindung am PC bleiben nur noch 4 Pins am Tiny über - einer davon ist der Reset-Eingang - wie soll man da großartig Ausgänge schalten können? Ganz zu schweigen von der angestrebten Erweiterbarkeit... Die Lösung hierfür ist einfach: der Mikrocontroller steuert Schieberegister an, die beliebig kaskadiert werden können. So kann man quasi beliebig viele Ausgänge an den AVR dengeln. Als Ausgabeschieberegister dienen 74xx595, welche einen Latch haben und die Datenleitungen in einem Rutsch aktualisiert werden können. Um Signale auch lesen zu können, kommen 74xx165 zum Einsatz. Zwar haben diese auch einen Latch, allerdings ist dieser (anders als beim 595) low-aktiv. Damit wird's mit 4 I/Os am AVR eng. Gut, die Strobe-Leitungen muss man trennen, Clock kann gemeinsam laufen, nur sind jetzt schon alle Pins belegt. Es ist zwar möglich, die Daten ins Register zu laden, aber was bringen die Daten, wenn man sie nicht lesen kann? Mit einem kleinen Trick kann man das aber bewältigen: Die Datenleitungen beider Richtungen auf einen I/O. Zum Schutz des Ausganges des Registers gibt es aber einen Reihenwiderstand. Zwischen dem Lesen und Schreiben muss die Datenleitung einfach nur noch als Eingang bzw. Ausgang geschaltet werden. <gallery> Bild:Usblotio_povray.jpg|Mit [http://www.povray.org/ POV-Ray] gerendertes Layout der Platinen Bild:Usblotio_main.jpg|Aufgebaute Hauptplatine des USBLotIO Bild:Usblotio out.jpg|Aufgebautes Ausgabemodul </gallery> Aber Vorsicht: dadurch, dass der Reset-Pin auch verwendet wird, kann der Mikrocontroller nur mit HVSP programmiert werden! (oder man lässt eine "Richtung" weg - noch ungetestet). <b style="color: red;">Ein Wort der Warnung sei noch angebracht:</b> Bei vielen PCs ist die USB-Schnittstelle NICHT abgesichert, bei einem Kurzschluss geht dann die komplette Leistung des Netzteils durch! Das kann zu zerstörten Leiterbahnen (sowohl am USB-Gerät als auch auf dem Mainboard) oder sogar Bränden führen! In der Firmware ist eine Stromaufnahme von 20mA angegeben, welche schon bei kleineren Aufbauten überschritten werden kann. Die Inbetriebnahme findet unter eigener Verantwortung statt! Rechnungen für neue Mainboards o.a. an mich werden mit Freude durch den Aktenvernichter gejagt. == Software == === AVR === Wie bereits erwähnt läuft auf dem AVR objective developments V-USB als HID. Grundlage für meine Implementierung war das "Datastore"-Beispiel, das zusätzlich um die automatische Kalibrierung der CPU-Frequenz erweitert wurde. Da die USB-Schnittstelle zwangsläufig auf einem Interrupt-Pin hängt, der gleichzeitig auch für SPI verantwortlich ist, müssen die Schieberegister mit einem wesentlich langsameren Soft-SPI angesprochen werden. Der USB-Client reagiert bei dem Beginn einer Übertragung mit einem Aufruf der Methode usbFunctionSetup. In ihr wird dann entschieden, ob es sich um einen Schreib- oder Lesevorgang handelt. Hier wird zum einen die Speicheradresse auf 0 gesetzt und beim Leseaufruf die Zustände der Registereingänge in den RAM geschrieben. Anschließend wird von V-USB usbFunctionWrite bzw. usbFunctionRead je nach Reportgröße mehrmals aufgerufen. Im Read wird einfach nur der Inhalt des RAMs an den PC übertragen, beim Schreiben wird zuerst die Variable (die gleiche wie beim Lesen) gefüllt und nach dem letzten Wert vom PC die Methode processCommand aufgerufen. Die übertragenen Werte werden in Anschlussreihenfolge aus Sicht der Hauptplatine angegeben. Gibt man z.B. 0x01 0x02 aus, wird am Ausgabemodul, das am nächsten zur Hauptplatine angeschlossen ist 0x01 ausgegeben, am "zweitnächsten" 0x02. Bei den Eingabemodulen verhält es sich genauso. Dort findet das eigentliche Schreiben auf die Register statt. Zusätzlich zum simplen Schreiben kann man den Controller mit ein paar Logikfunktionen beauftragen. Diese werden immer mit der letzten Ausgabe verarbeitet. Folgende Operationen sind möglich: * Überschreiben * OR * AND * XOR Zusätzlich kann man ein Flag zum Invertieren übergeben, dadurch werden die Funktionen NOR, NAND und XNOR sowie invertiertes Überschreiben ermöglicht. Mit einem weiteren Flag kann man die errechneten Werte ins EEProm des Controllers schreiben. Dadurch kann man direkt beim Einschalten der Hardware einen definierten Zustand ausgeben. Das einzige, das man in der Software noch anpassen muss, ist die Anzahl der jeweiligen Schieberegister. Oder einfach unverändert lassen - dann werden jeweils 8 Register angenommen. Diese Werte muss man nur anpassen, wenn man mehr als 8 Schieberegister verwendet oder mehr Performance (Auswirkung noch nicht geprüft) wünscht. Ferner kann man eine ID in den EEProm schreiben, um mehrere (256) Devices zu unterscheiden. Diese ID wird bei jedem Lese-Vorgang im untersten Byte des Reports zurückgegeben. [[Bild:Usblotio_fuses.png|thumb|Im AVR programmierte Fuses]] Damit man die Hardware vollständig genutzt werden kann, müssen die Fuses wie folgt programmiert werden (siehe auch Screenshot): * Extended: 0xFF * High: 0x75 * Low: 0xE1 SPIEN kann nur deaktiviert werden, wenn man per HVSP programmiert, RSTDISBL ''sollte'' eigentlich reichen, habe ich allerdings nicht ausprobiert ;-) === PC === Auf dem PC kann eigentlich alles werkeln, was auf die entsprechenden USB-APIs zugreifen kann. Ich beschränke mich auf Windows, die Portierung auf *nix/Mac/etc. sollte aber nicht allzu schwierig sein. Im Grunde muss man nicht viel machen, das Schwierigste dürfte wahrscheinlich das Finden des Devices sein. Ich habe im C#-Programm Teile aus der [http://www.brianpeek.com/blog/pages/wiimotelib.aspx WiimoteLib] von Brian Peek genommen. Ist das HID gefunden und ein Handler gesetzt, können mit HidD_SetFeature und -GetFeature Reports an den AVR gesendet oder von ihm angefordert werden. Wichtig ist hier eigentlich nur die Größe des übergebenen Arrays, bei falscher Länge kommt oft einfach nichts beim Device an! Man kann relativ viel Zeit damit verbringen, dort nach einem Fehler zu suchen, zumal sich ein vollbelegter Mikrocontroller (dessen UART man nicht verwenden kann) schlecht debuggen lässt. Zur Demonstration habe ich eine kleine Konsolen-Anwendung rund um die USBLotIO-Klasse geschrieben. Kann sein, dass ich die Klasse noch ein wenig umstrukturiere - die nullable Byte-Arrays gefallen mir nicht sonderlich. Im Ordner \csharp\USBlotIO\bin\Release\ befindet sich ein kleines Konsolenprogramm (USBlotIO.exe), mit dem man alle Features der Hardware testen/nutzen kann. Einfach einmal ohne Parameter starten, dann werden alle möglichen Aufrufe angezeigt (wem es beim Start per Doppelklick zu schnell geht: cmd starten und damit die Anwendung aufrufen). == Test == Die Hardwareinstallation ist im Baukastenprinzip. Module anstecken und per USB-Kabel mit dem PC verbinden. Nach wenigen Sekunden ist das Gerät bereit für die Verwendung. Leider konnte ich das Board für Eingabemodule nicht testen, da Reichelt keine 74xx165 in SMD hat. Auf dem Breadboard hat es funktioniert, dennoch gebe ich momentan keine 100%ige Garantie auf korrekte Funktion! Erfolgreich getestet wurde die C#-Anwendung bisher unter WinXP Pro SP3 sowie Windows 7. Für Vista brauche ich erst noch einen Probanden, Windows 2000 lasse ich außen vor (freue mich aber über Erfolgsmeldungen). == Download == [[Datei:Usblotio.zip]] Firmware, EAGLE-Dateien und C#-Testprogramm (VS2008, .NET 2.0) [[Category:AVR]] [[Category:USB]] [[Category:PC]] 5212358407a3c4511f870908b03847ef887d7d25 VBus-Decoder 0 120 449 411 2010-06-13T11:55:38Z Chris 2 Infobox AVR hinzugefügt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = 0xCF | FuseL = 0xFF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die zwar Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <pre> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </pre> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <pre> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </pre> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Maschinen]] 012b7a8880e5007467235b6a36e10a28f7a5f3ec 472 449 2010-07-08T19:03:35Z Chris 2 Fuses angepasst wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die zwar Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <pre> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </pre> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <pre> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </pre> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Maschinen]] 9013ef20abbef0a2fca8368b34f575a729b7c760 Vorlage:Infobox AVR/Doku 10 140 450 441 2010-06-13T11:59:06Z Chris 2 Beispiel hinzugefügt wikitext text/x-wiki <pre><nowiki> {{Infobox AVR | Typ = | Takt = | FuseH = | FuseL = | FuseE = }} </nowiki></pre> = Beispiel = {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = 0xDD | FuseL = 0xE1 | FuseE = 0xFF }} 8d49c2e6c26d2f4b32aeccaa6c01bd3e2d535b2e 452 450 2010-06-13T12:00:44Z Chris 2 Beispiel vervollständigt wikitext text/x-wiki <pre><nowiki> {{Infobox AVR | Typ = | Takt = | FuseH = | FuseL = | FuseE = }} </nowiki></pre> = Beispiel = <pre><nowiki> {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = 0xDD | FuseL = 0xE1 | FuseE = 0xFF }} </nowiki></pre> {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = 0xDD | FuseL = 0xE1 | FuseE = 0xFF }} 7e077cb76e60b58aba48a5f85df78456b6063093 460 452 2010-07-08T18:22:31Z Chris 2 wikitext text/x-wiki <pre><nowiki> {{Infobox AVR | Typ = | Takt = | FuseH = | FuseL = | FuseE = }} </nowiki></pre> = Beispiel = <pre><nowiki> {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = DD | FuseL = E1 | FuseE = FF }} </nowiki></pre> {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = DD | FuseL = E1 | FuseE = FF }} ca831fd584174674b798f452798f317070325487 Vorlage:Infobox AVR 10 139 451 443 2010-06-13T11:59:25Z Chris 2 wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox prettytable" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || {{{FuseH}}} |- | Low || {{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} {{{FuseE}}} }} |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:AVR]]}} </onlyinclude> 78d219d5e27cccfc5f5889d76109da7fd87d7b43 457 451 2010-07-08T18:20:40Z Chris 2 Fusecalc auf engbedded.com verlinkt wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox prettytable" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || 0x{{{FuseH}}} |- | Low || 0x{{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} 0x{{{FuseE}}} }} |- ! colspan="2" | [http://www.engbedded.com/fusecalc?P={{{Typ}}}&V_LOW={{{FuseL}}}&V_HIGH={{{FuseH}}}{{#if:{{{FuseE|}}}&V_EXTENDED={{{FuseE}}}}} Details] |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:AVR]]}} </onlyinclude> eff2a204cf5284421a84f3fe1ed519667970a5cd 458 457 2010-07-08T18:21:09Z Chris 2 wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox prettytable" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || 0x{{{FuseH}}} |- | Low || 0x{{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} 0x{{{FuseE}}} }} |- ! colspan="2" | [http://www.engbedded.com/fusecalc?P={{{Typ}}}&V_LOW={{{FuseL}}}&V_HIGH={{{FuseH}}}{{#if:{{{FuseE|}}}&V_EXTENDED={{{FuseE}}}}} Details] |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:AVR]]}} </onlyinclude> 27467226719155d25299165e8aa02610cb2f20c8 459 458 2010-07-08T18:21:58Z Chris 2 wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox prettytable" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || 0x{{{FuseH}}} |- | Low || 0x{{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} 0x{{{FuseE}}} }} |- ! colspan="2" | [http://www.engbedded.com/fusecalc?P={{{Typ}}}&V_LOW={{{FuseL}}}&V_HIGH={{{FuseH}}}{{#if:{{{FuseE|}}}&V_EXTENDED={{{FuseE}}}}} Details] |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:AVR]]}} </onlyinclude> 25d8b04bbef38e91057992ca8d284c4c38f0d598 462 459 2010-07-08T18:39:48Z Chris 2 Apply+values vergessen wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox prettytable" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || 0x{{{FuseH}}} |- | Low || 0x{{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} 0x{{{FuseE}}} }} |- ! colspan="2" | [http://www.engbedded.com/fusecalc?P={{{Typ}}}&V_LOW={{{FuseL}}}&V_HIGH={{{FuseH}}}{{#if:{{{FuseE|}}}&V_EXTENDED={{{FuseE}}}}}&O_HEX=Apply+values Details] |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:AVR]]}} </onlyinclude> 4adecfaf8f1495f4e00389aa0566347f223fb413 464 462 2010-07-08T18:57:11Z Chris 2 Engbedded-Logo hinzugefügt wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox prettytable" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || 0x{{{FuseH}}} |- | Low || 0x{{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} 0x{{{FuseE}}} }} |- ! colspan="2" | <nowiki><a href="http://www.engbedded.com" target="_blank"><img src="images/f/ff/Engbedded_com_logo.png" /></a></nowiki> [http://www.engbedded.com/fusecalc?P={{{Typ}}}&V_LOW={{{FuseL}}}&V_HIGH={{{FuseH}}}{{#if:{{{FuseE|}}}&V_EXTENDED={{{FuseE}}}}}&O_HEX=Apply+values Details] |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:AVR]]}} </onlyinclude> 6ae8a89e6f6835921391977909bba0aa99b33808 465 464 2010-07-08T18:57:49Z Chris 2 hmpf wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox prettytable" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || 0x{{{FuseH}}} |- | Low || 0x{{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} 0x{{{FuseE}}} }} |- ! colspan="2" | <a href="http://www.engbedded.com" target="_blank"><img src="images/f/ff/Engbedded_com_logo.png" /></a> [http://www.engbedded.com/fusecalc?P={{{Typ}}}&V_LOW={{{FuseL}}}&V_HIGH={{{FuseH}}}{{#if:{{{FuseE|}}}&V_EXTENDED={{{FuseE}}}}}&O_HEX=Apply+values Details] |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:AVR]]}} </onlyinclude> d4a244c6c830356acd92c1ea9a320f51865bcc23 466 465 2010-07-08T18:58:52Z Chris 2 wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox prettytable" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || 0x{{{FuseH}}} |- | Low || 0x{{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} 0x{{{FuseE}}} }} |- ! colspan="2" | <nowiki><a href="http://www.engbedded.com" target="_blank"><img src="images/f/ff/Engbedded_com_logo.png" /></a></nowiki> [http://www.engbedded.com/fusecalc?P={{{Typ}}}&V_LOW={{{FuseL}}}&V_HIGH={{{FuseH}}}{{#if:{{{FuseE|}}}&V_EXTENDED={{{FuseE}}}}}&O_HEX=Apply+values Details] |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:AVR]]}} </onlyinclude> 6ae8a89e6f6835921391977909bba0aa99b33808 467 466 2010-07-08T19:01:01Z Chris 2 der Link mag mich nicht... wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox prettytable" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || 0x{{{FuseH}}} |- | Low || 0x{{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} 0x{{{FuseE}}} }} |- ! colspan="2" | [http://www.engbedded.com/fusecalc?P={{{Typ}}}&V_LOW={{{FuseL}}}&V_HIGH={{{FuseH}}}{{#if:{{{FuseE|}}}&V_EXTENDED={{{FuseE}}}}}&O_HEX=Apply+values Details] |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:AVR]]}} </onlyinclude> 4adecfaf8f1495f4e00389aa0566347f223fb413 473 467 2010-07-08T19:07:00Z Chris 2 mal sehen, ob es jetzt klappt... wikitext text/x-wiki {{Dokumentation}}<onlyinclude>{| class="float-right wikitable infobox prettytable" id="vorlage-infobox-AVR" summary="Infobox AVR" |- class="hintergrundfarbe6" ! colspan="2" | AVR |- | Typ || {{{Typ}}} |- | Takt || {{{Takt}}} MHz |- ! colspan="2" | Fuses |- | High || 0x{{{FuseH}}} |- | Low || 0x{{{FuseL}}} |- Zeilen-Attribute {{#if:{{{FuseE|}}} | {{!}} Extended{{!!}} 0x{{{FuseE}}} }} |- ! colspan="2" | [[Datei:Engbedded_com_logo.png|link=http://www.engbedded.com]] [http://www.engbedded.com/fusecalc?P={{{Typ}}}&V_LOW={{{FuseL}}}&V_HIGH={{{FuseH}}}{{#if:{{{FuseE|}}}&V_EXTENDED={{{FuseE}}}}}&O_HEX=Apply+values Details] |} {{#ifeq:{{NAMESPACE}}|{{ns:0}}|[[Kategorie:AVR]]}} </onlyinclude> ebc2439e195c675743a2ac9d0affd1be4c1cbf52 Hauptseite 0 1 453 426 2010-06-13T12:17:58Z Chris 2 Änderungen Infobox wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *04.03.2010 [[VBus-Decoder]] *24.02.2010 [[UnitColor]] *12.02.2010 [[Panasonic-Zapper]] *27.12.2009 [[USBLotIO]] *04.07.2009 [[Touchlight]] =Updates= *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) 1dfef2ea9b4bc72651deea0e7b68d68b2918667a 489 453 2010-07-15T14:45:40Z Chris 2 /* Neues */ wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *15.07.2010 [[Nokia 5110 Displayadapter]] *09.07.2010 [[Sommerhitz]] *04.03.2010 [[VBus-Decoder]] *24.02.2010 [[UnitColor]] *12.02.2010 [[Panasonic-Zapper]] =Updates= *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) dcadf1cfcf82abd5b8165ed9a99a843f78c2e0aa Datei:Hitz1.png 6 142 454 2010-07-03T06:14:06Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Hitz2.png 6 143 455 2010-07-03T06:14:34Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Sommerhitz 0 144 456 2010-07-03T06:17:00Z Chris 2 Mir ist so heiß... wikitext text/x-wiki Der Sommer ist da! Nur bin ich verdonnert, auf Klausuren zu lernen. So weit eigentlich nicht schlimm, würde die Hitze draußen bleiben. Obwohl ich bereits beim Einzug ins Haus ein Ostseite-Zimmer wollte (ich wollte Gartenblick und eben Kühle und das als 6-jähriger!), bestimmten die Eltern "ihr sollt Sonne am Nachmittag haben". Das war insoweit irrelevant, dass ich bei gutem Wetter eh draußen war und die Hausaufgaben nicht in meinem Zimmer gemacht habe (und durch meine Unordnung manchmal auch nicht machen konnte *g*). Aber das nur am Rande... = Erste Lösung = Irgendwann bekamen wir dann doch Ventilatoren, um zumindest für Zirkulation zu sorgen. Als dann in Physik Verdunstungskälte dran kam, hängten jeden Sommer nasse Waschlappen am Miefquirl. Bedingt durch die Aufhängevorrichtung so lange, bis die Laschen an den Lappen durchgebrochen sind. Die gefühlte Wirkung war vorhanden, gemessen hatte ich dazu nichts. = Messung = Warum ich nicht schon früher auf die Idee gekommen bin? Auch wenn ich vor ein paar Jahren ziemlich versessen auf DS75 von Maxim war, kam mir bis dahin nicht größer in den Sinn, die Raumtemperatur zu protokollieren und analysieren. Das habe ich nachgeholt. Um den technischen Aufwand gering zu halten, kommt eine Schaltung zum Einsatz, die schon an zwei Orten (Serverraum meines Arbeitgebers und eines Kollegen) läuft: Ein Temperaturlogger - ein USB-Stick mit Anschlussmöglichkeit von I²C-Sensoren. Schnell auf dem Steckbrett aufgebaut und an einem herumliegenden Notebook angeschlossen, läuft die Protokollierung innerhalb von 15 Minuten. Die Software schreibt alle 5 Minuten Datum, Zeit und sämtliche gemessenen Werte Tab-getrennt in eine Textdatei, die direkt per Apache von überall auf der Welt heruntergeladen werden kann. Zusätzlich liegt eine kleine PHP-Datei auf dem Server, die die aktuellen Temperaturwerte ausspuckt, damit ich nicht jedes mal die komplette Datei herunterladen und nach unten scrollen muss. Drei Sensoren wurden wie folgt verteilt: Zimmerdecke, Schreibtischöhe und aus dem Fenster baumelnd. Letzterer ist etwas kritisch, da er am Nachmittag direkt in der Sonne steht und somit übermäßig erwärmt wird. Um dem entgegen zu wirken, ist er in Aluminiumklebeband eingewickelt, was seinen Dienst anscheinend recht gut erfüllt. = Auswertung = Die Aufzeichnung beginnt am 30.06.2010 um 19:19:09 und ist bis auf 5 Messungen (AVR abgeschmiert) durchgängig. [[Datei:Hitz1.png|200px]] Im Diagramm sieht fallen sofort die großen Sprünge am Nachmittag auf. Ich kann diese zwar auch noch nicht genau erklären, vermute aber, dass der Sensor hier voll in der Sonne steht. Durch Wolken, Wind und dem geringen Volumen des Sensors (DS1775) dürfte die Temperatur in ihm also ziemlich stark schwanken. Woher das Gezitter in der Nacht kommt, kann ich abgesehen vom Wind nicht erklären. Im zweiten Diagramm sind die Temperaturunterschiede Außen-Innen (Innen = Mittelwert aus Decke und Tisch) und Decke-Tisch zu sehen: [[Datei:Hitz2.png|200px]] Die blaue Linie zeigt an, wann es sich theoretisch lohnt, das Fenster zu öffnen: Sobald die Linie unter 0 geht ist es draußen kälter oder zumindest gleich warm. Kühlperiode ist demnach von 19:20 bis 11:00. Anhand der Differenz im Inneren kann man ziemlich genau sehen, wann der Ventilator lief: Ist ohne Rheumarschraube die Temperatur oben höher, sinkt sie rapide ab, wenn die Zirkulation angekurbelt wird. Demnach lief der Lüfter am ersten Tag von 16:15 bis 17:45 und 18:45 bis 20:30. Am zweiten Tag kann man die Sprünge nicht mehr ganz so gut sehen, da ich dort anders gelüftet/ventiliert habe. Die nahezu gleiche Betriebsdauer ist übrigens dadurch begründet, dass am Lüfter ein Zeitrelais (eingestellt auf 100 Minuten) hängt. = Konsequenzen = Um die Abkühlung außen besser zu nutzen, habe ich den Lüfter per Zeitschaltuhr am zweiten Tag von 4:30 bis 7:00 laufen lassen, was man zwar an dem leichten Knick (rot) im Diagramm sehen kann - an der Temperatur hat sich aber nicht sonderlich viel getan (großzügig gerechnet 2°C). bleibt nur noch übrig, die Wirkung der Waschlappen zu messen. Hygrometer habe ich leider noch nicht für den USB... ''to be continued...'' [[Kategorie:Sonstiges]] 3f96b41c312cd19d4a66ef8bd64370e957db0b6a 479 456 2010-07-09T20:52:34Z Chris 2 Mehr Daten wikitext text/x-wiki Der Sommer ist da! Nur bin ich verdonnert, auf Klausuren zu lernen. So weit eigentlich nicht schlimm, würde die Hitze draußen bleiben. Obwohl ich bereits beim Einzug ins Haus ein Ostseite-Zimmer wollte (ich wollte Gartenblick und eben Kühle und das als 6-jähriger!), bestimmten die Eltern "ihr sollt Sonne am Nachmittag haben". Das war insoweit irrelevant, dass ich bei gutem Wetter eh draußen war und die Hausaufgaben nicht in meinem Zimmer gemacht habe (und durch meine Unordnung manchmal auch nicht machen konnte *g*). Aber das nur am Rande... = Erste Lösung = Irgendwann bekamen wir dann doch Ventilatoren, um zumindest für Zirkulation zu sorgen. Als dann in Physik Verdunstungskälte dran kam, hängten jeden Sommer nasse Waschlappen am Miefquirl. Bedingt durch die Aufhängevorrichtung so lange, bis die Laschen an den Lappen durchgebrochen sind. Die gefühlte Wirkung war vorhanden, gemessen hatte ich dazu nichts. = Messung = [[Datei:Hitzboard.jpg|thumb|Der Messaufbau. Displays werden überbewertet.]] Warum ich nicht schon früher auf die Idee gekommen bin? Auch wenn ich vor ein paar Jahren ziemlich versessen auf DS75 von Maxim war, kam mir bis dahin nicht größer in den Sinn, die Raumtemperatur zu protokollieren und analysieren. Das habe ich nachgeholt. Um den technischen Aufwand gering zu halten, kommt eine Schaltung zum Einsatz, die schon an zwei Orten (Serverraum meines Arbeitgebers und eines Kollegen) läuft: Ein Temperaturlogger - ein USB-Stick mit Anschlussmöglichkeit von I²C-Sensoren. Schnell auf dem Steckbrett aufgebaut und an einem herumliegenden Notebook angeschlossen, läuft die Protokollierung innerhalb von 15 Minuten. Die Software schreibt alle 5 Minuten Datum, Zeit und sämtliche gemessenen Werte Tab-getrennt in eine Textdatei, die direkt per Apache von überall auf der Welt heruntergeladen werden kann. Zusätzlich liegt eine kleine PHP-Datei auf dem Server, die die aktuellen Temperaturwerte ausspuckt, damit ich nicht jedes mal die komplette Datei herunterladen und nach unten scrollen muss. Drei Sensoren wurden wie folgt verteilt: Zimmerdecke, Schreibtischöhe und aus dem Fenster baumelnd. Letzterer ist etwas kritisch, da er am Nachmittag direkt in der Sonne steht und somit übermäßig erwärmt wird. Um dem entgegen zu wirken, ist er in Aluminiumklebeband eingewickelt, was seinen Dienst anscheinend recht gut erfüllt. = Auswertung = Die Aufzeichnung beginnt am 30.06.2010 um 19:19:09 und ist bis auf 5 Messungen (AVR abgeschmiert) durchgängig. [[Datei:Hitz1.png|200px]] Im Diagramm sieht fallen sofort die großen Sprünge am Nachmittag auf. Ich kann diese zwar auch noch nicht genau erklären, vermute aber, dass der Sensor hier voll in der Sonne steht. Durch Wolken, Wind und dem geringen Volumen des Sensors (DS1775) dürfte die Temperatur in ihm also ziemlich stark schwanken. Woher das Gezitter in der Nacht kommt, kann ich abgesehen vom Wind nicht erklären. Im zweiten Diagramm sind die Temperaturunterschiede Außen-Innen (Innen = Mittelwert aus Decke und Tisch) und Decke-Tisch zu sehen: [[Datei:Hitz2.png|200px]] Die blaue Linie zeigt an, wann es sich theoretisch lohnt, das Fenster zu öffnen: Sobald die Linie unter 0 geht ist es draußen kälter oder zumindest gleich warm. Kühlperiode ist demnach von 19:20 bis 11:00. Anhand der Differenz im Inneren kann man ziemlich genau sehen, wann der Ventilator lief: Ist ohne Rheumarschraube die Temperatur oben höher, sinkt sie rapide ab, wenn die Zirkulation angekurbelt wird. Demnach lief der Lüfter am ersten Tag von 16:15 bis 17:45 und 18:45 bis 20:30. Am zweiten Tag kann man die Sprünge nicht mehr ganz so gut sehen, da ich dort anders gelüftet/ventiliert habe. Die nahezu gleiche Betriebsdauer ist übrigens dadurch begründet, dass am Lüfter ein Zeitrelais (eingestellt auf 100 Minuten) hängt. = Konsequenzen = Um die Abkühlung außen besser zu nutzen, habe ich den Lüfter per Zeitschaltuhr am zweiten Tag von 4:30 bis 7:00 laufen lassen, was man zwar an dem leichten Knick (rot) im Diagramm sehen kann - an der Temperatur hat sich aber nicht sonderlich viel getan (großzügig gerechnet 2°C). bleibt nur noch übrig, die Wirkung der Waschlappen zu messen. Hygrometer habe ich leider noch nicht für den USB... = Mehr Daten = Nachdem ich die Messung mehr oder weniger abgeschlossen habe, möchte ich die Daten natürlich nicht vorenthalten. Die Messung wurde vom 01.07.2010 15:20 bis zum 06.07.2010 22:30 durchgeführt. Durch einen Soft- bzw. Hardwarefehler fehlen vom 02.07. zwischen 19:25 und 19:45 die Daten vollständig. <gallery> Datei:Hitz3.png|Temperaturverlauf der gesamten Messung Datei:Hitz4.png|Vergleich der Außentemperaturen Datei:Hitz5.png|Temperaturdifferenzen </gallery> Aus den Daten sieht man, dass die Tage (besonders der 02.07. und 03.07.) ziemlich ähnlich waren. Am 06.07. war es nur leicht bewölkt, was aber sehr großen Einfluss auf die Temperaturen hatte. Das starke Zittern der Werte kommt anscheinend tatsächlich vom Wind. Nachdem der Ventilator am 06.07. in der Früh ziemlich genau auf den Temperatursensor ausgerichtet war (und es außen auch leicht windete) kann man dort auch ziemlich starke Schwankungen sehen. Die Dinger müssen also eine ziemlich geringe spez. Wärmekapazität haben. Gut, wenn man schnelle und leichte Schwankungen erfassen will. Wer die Daten noch weiter verwursten will, kann sich die Excel-Dateien (XLSX) herunterladen. Für Puristen sind die Protokolldaten auch als CSV-Datei in der Zip: [[Datei:Templog.zip]] [[Kategorie:Sonstiges]] e0da5ea1d8a278a17ea3222ede9e1ce3946b9d78 480 479 2010-07-09T21:12:55Z Chris 2 Resultat wikitext text/x-wiki Der Sommer ist da! Nur bin ich verdonnert, auf Klausuren zu lernen. So weit eigentlich nicht schlimm, würde die Hitze draußen bleiben. Obwohl ich bereits beim Einzug ins Haus ein Ostseite-Zimmer wollte (ich wollte Gartenblick und eben Kühle und das als 6-jähriger!), bestimmten die Eltern "ihr sollt Sonne am Nachmittag haben". Das war insoweit irrelevant, dass ich bei gutem Wetter eh draußen war und die Hausaufgaben nicht in meinem Zimmer gemacht habe (und durch meine Unordnung manchmal auch nicht machen konnte *g*). Aber das nur am Rande... = Erste Lösung = Irgendwann bekamen wir dann doch Ventilatoren, um zumindest für Zirkulation zu sorgen. Als dann in Physik Verdunstungskälte dran kam, hängten jeden Sommer nasse Waschlappen am Miefquirl. Bedingt durch die Aufhängevorrichtung so lange, bis die Laschen an den Lappen durchgebrochen sind. Die gefühlte Wirkung war vorhanden, gemessen hatte ich dazu nichts. = Messung = [[Datei:Hitzboard.jpg|thumb|Der Messaufbau. Displays werden überbewertet.]] Warum ich nicht schon früher auf die Idee gekommen bin? Auch wenn ich vor ein paar Jahren ziemlich versessen auf DS75 von Maxim war, kam mir bis dahin nicht größer in den Sinn, die Raumtemperatur zu protokollieren und analysieren. Das habe ich nachgeholt. Um den technischen Aufwand gering zu halten, kommt eine Schaltung zum Einsatz, die schon an zwei Orten (Serverraum meines Arbeitgebers und eines Kollegen) läuft: Ein Temperaturlogger - ein USB-Stick mit Anschlussmöglichkeit von I²C-Sensoren. Schnell auf dem Steckbrett aufgebaut und an einem herumliegenden Notebook angeschlossen, läuft die Protokollierung innerhalb von 15 Minuten. Die Software schreibt alle 5 Minuten Datum, Zeit und sämtliche gemessenen Werte Tab-getrennt in eine Textdatei, die direkt per Apache von überall auf der Welt heruntergeladen werden kann. Zusätzlich liegt eine kleine PHP-Datei auf dem Server, die die aktuellen Temperaturwerte ausspuckt, damit ich nicht jedes mal die komplette Datei herunterladen und nach unten scrollen muss. Drei Sensoren wurden wie folgt verteilt: Zimmerdecke, Schreibtischöhe und aus dem Fenster baumelnd. Letzterer ist etwas kritisch, da er am Nachmittag direkt in der Sonne steht und somit übermäßig erwärmt wird. Um dem entgegen zu wirken, ist er in Aluminiumklebeband eingewickelt, was seinen Dienst anscheinend recht gut erfüllt. = Auswertung = Die Aufzeichnung beginnt am 30.06.2010 um 19:19:09 und ist bis auf 5 Messungen (AVR abgeschmiert) durchgängig. [[Datei:Hitz1.png|200px]] Im Diagramm sieht fallen sofort die großen Sprünge am Nachmittag auf. Ich kann diese zwar auch noch nicht genau erklären, vermute aber, dass der Sensor hier voll in der Sonne steht. Durch Wolken, Wind und dem geringen Volumen des Sensors (DS1775) dürfte die Temperatur in ihm also ziemlich stark schwanken. Woher das Gezitter in der Nacht kommt, kann ich abgesehen vom Wind nicht erklären. Im zweiten Diagramm sind die Temperaturunterschiede Außen-Innen (Innen = Mittelwert aus Decke und Tisch) und Decke-Tisch zu sehen: [[Datei:Hitz2.png|200px]] Die blaue Linie zeigt an, wann es sich theoretisch lohnt, das Fenster zu öffnen: Sobald die Linie unter 0 geht ist es draußen kälter oder zumindest gleich warm. Kühlperiode ist demnach von 19:20 bis 11:00. Anhand der Differenz im Inneren kann man ziemlich genau sehen, wann der Ventilator lief: Ist ohne Rheumarschraube die Temperatur oben höher, sinkt sie rapide ab, wenn die Zirkulation angekurbelt wird. Demnach lief der Lüfter am ersten Tag von 16:15 bis 17:45 und 18:45 bis 20:30. Am zweiten Tag kann man die Sprünge nicht mehr ganz so gut sehen, da ich dort anders gelüftet/ventiliert habe. Die nahezu gleiche Betriebsdauer ist übrigens dadurch begründet, dass am Lüfter ein Zeitrelais (eingestellt auf 100 Minuten) hängt. = Konsequenzen = Um die Abkühlung außen besser zu nutzen, habe ich den Lüfter per Zeitschaltuhr am zweiten Tag von 4:30 bis 7:00 laufen lassen, was man zwar an dem leichten Knick (rot) im Diagramm sehen kann - an der Temperatur hat sich aber nicht sonderlich viel getan (großzügig gerechnet 2°C). bleibt nur noch übrig, die Wirkung der Waschlappen zu messen. Hygrometer habe ich leider noch nicht für den USB... = Mehr Daten = Nachdem ich die Messung mehr oder weniger abgeschlossen habe, möchte ich die Daten natürlich nicht vorenthalten. Die Messung wurde vom 01.07.2010 15:20 bis zum 06.07.2010 22:30 durchgeführt. Durch einen Soft- bzw. Hardwarefehler fehlen vom 02.07. zwischen 19:25 und 19:45 die Daten vollständig. <gallery> Datei:Hitz3.png|Temperaturverlauf der gesamten Messung Datei:Hitz4.png|Vergleich der Außentemperaturen Datei:Hitz5.png|Temperaturdifferenzen </gallery> Aus den Daten sieht man, dass die Tage (besonders der 02.07. und 03.07.) ziemlich ähnlich waren. Am 06.07. war es nur leicht bewölkt, was aber sehr großen Einfluss auf die Temperaturen hatte. Das starke Zittern der Werte kommt anscheinend tatsächlich vom Wind. Nachdem der Ventilator am 06.07. in der Früh ziemlich genau auf den Temperatursensor ausgerichtet war (und es außen auch leicht windete) kann man dort auch ziemlich starke Schwankungen sehen. Die Dinger müssen also eine ziemlich geringe spez. Wärmekapazität haben. Gut, wenn man schnelle und leichte Schwankungen erfassen will. Wer die Daten noch weiter verwursten will, kann sich die Excel-Dateien (XLSX) herunterladen. Für Puristen sind die Protokolldaten auch als CSV-Datei in der Zip: [[Datei:Templog.zip]] = Resultat = * Die niedrigsten Außentemperaturen sind ca. zwischen 4:00 und 7:00 Uhr * Lüften am Besten zwischen 22:00 und 8:00 Uhr * Zwischen 11:00 und 19:30 Fenster besser geschlossen halten (Temperaturdifferenz Innen/Außen!) * Die Verdunstungskälte auch von mehreren nassen Waschlappen am Ventilator ist verschwindend gering * Der Ventilator quirlt die Warme Luft unter der Decke nach unten, schafft aber durch die Verdunstungskälte auf der Haut ein nicht-mehr-ganz-so-heiß-Gefühl * Viel trinken * Anstrengungen vermeiden Achja: Eis essen oder kühle Getränke bringen nur vorübergehende Erfrischung. Da der Mensch im Inneren halt doch seine 37°C ausreguliert, ist der "Kühlungseffekt" schnell dahin. Ganz im Gegenteil sollte man sogar warme Dinge zu sich nehmen (siehe Südländer: heißer (und starker) Tee!). Ansonsten: Auch mal warm duschen. Dadurch werden die Poren geöffnet (-> Schwitzen) und die Außentemperaturen relativieren sich ;) [[Kategorie:Sonstiges]] 5fca18cf5daf2467b4781386d07183df7e1ecbac AVR-Doper 0 44 461 446 2010-07-08T18:23:14Z Chris 2 Fuses angepasst wikitext text/x-wiki {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = C9 | FuseL = 9F }} Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Ich habe auch damit angefangen, eine SMD-Version der Platine zu machen, allerdings gibt es ein paar Platzprobleme (der ATMega in TQFP ist einfach zu klein für die ganzen Bauteile außen herum). Die Firmware wurde nicht verändert und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download des optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] [[Category:AVR]] [[Category:USB]] [[Category:PC]] b8bc70733aaea6c5b1adfdad4a7e0b92b6b2721f Datei:Engbedded com logo.png 6 145 463 2010-07-08T18:54:37Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Panasonic-Zapper 0 112 468 445 2010-07-08T19:01:55Z Chris 2 Fuses angepasst wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny13 | Takt = 9,6 | FuseH = F9 | FuseL = 7A }} Mein Vater hat, wie viele, die Angewohnheit, vor dem Fernseher einzuschlafen. Soweit nicht schlimm, allerdings geht es auf Dauer unnötigerweise auf die Stromrechnung und die Flimmerkiste wird dadurch auch nicht jünger. Manchmal kommt noch jemand am Wohnzimmer vorbei und schaltet das Gerät ab. Das muss doch auch einfacher gehen... =Ideen= Meine erste Idee war, dem Teil per Zeitschaltuhr zumindest für eine Minute pro Nacht den Saft abzudrehen. Anders als unser alter Telefunken geht der Panasonic nach Spannungsrückkehr _nicht_ in den Stand-By. Genauso ist ihm die 12V-Steuerspannung am Scart grundsätzlich egal, sodass man selbes Spiel mit dem SAT-Receiver treiben könnte. Die zweite Idee war (auch noch vor dem Erlangen von Kenntnissen in der µC-Programmierung) war, eine Universal-Fernbedienung mit einem Wecker zu verheiraten. Blöd nur: Der Wecker schaltet seinen Alarmkontakt für einige Minuten, die Fernbedienung wird also unnötig lange betätigt, die Batterien gehen schnell leer und man hat eine Aperatur, die zwei Mal am Tag die Glotze abdreht und gleichzeitig die Fernbedienung zum wiederanschalten in dieser Zeit blockiert. Das hat weder [http://de.wikipedia.org/wiki/Woman_acceptance_factor WAF] noch <span title="father acceptance factor">FAF</span>. Das mit der Universal-Fernbedienung habe ich daher auch relativ schnell verworfen, die Idee mit dem Wecker blieb noch eine Weile. =Die Lösung= Der nächste Ansatz war, die Fernbedienung in einem Mikrocontroller nachzubilden. Seit dem [http://ladyada.net/make/tvbgone/ TV-B-Gone] ist das massenhafte Abschalten von TV-Geräten ein Geek-Volkssport geworden. Ein guter Ansatz. Als nächstes schaute ich mir die [http://lirc.sourceforge.net/remotes/ Fernbedienungs-Bibliothek von LIRC] an. Von Panasonic gibt es genügend Codes. Allerdings keinen, der (auf den ersten Blick) exakt auf die Fernbedienung hier passt. Also: Fototranse an die Soundkarte anklemmen, aufnehmen ([[Datei:Panasonic.wav]]) und genauer anschauen (z. B. mit [http://audacity.sourceforge.net/ Audacity]). Netterweise war die Soundkarte lahm und übersteuert genug, dass man keinen 38kHz-Filter auf die Aufnahme anwenden musste (an den Flanken sieht man noch ein bisschen was). Mit Papier und Bleistift habe ich dann das Protokoll analysiert und vollständige Übereinstimmung zu einer Definition von LIRC gefunden. Muss das Signal nur noch nachgebaut werden. Die Ausgabe der Bytes ist kein Problem, nur das Trägersignal von 38kHz macht mir etwas Sorgen. Zwar kann man dies auch mit C halbwegs gut zu Fuß ausgeben, muss aber beim Timing etwas aufpassen. Netterweise kann man selbst mit dem sonst recht schwachen ATtiny13 hardwareseitig Signale mit einem Rechteck moduliert ausgeben. Spart man sich einen NE555 bzw. nervige Timinganpassungen. Den Code hierfür habe ich auch beim TV-B-Gone wiederentdeckt. Nachdem der Fernbedienungscode dem Mikrocontroller beigebracht und das Timing noch ein bisschen angepasst wurde (kommt auf 99% an das Original heran), ging die Überlegerei wieder los: wie auslösen? Hier kommt der Wecker wieder ins Spiel: Statt meinen Vater zu wecken (damit er den Fernseher abstellt), kann der doch die Stromversorgung schalten. Blöd auch hier wieder: Zwei Spannungsquellen, weil der AVR halbwegs genau 5V sehen will, da sonst der RC-Taktgeber einen zu niedrigen Takt ausgibt und von der IR-LED nur noch Kauderwelsch kommt. Außerdem sind Wecker unerhört teuer - da lohnt es sich schon fast, eine RTC samt Display an den kleinen anzuschließen. Totaler Overkill ==Die bessere Lösung== Irgendwann fiel es mir wie Schuppen von den Augen: Das deutlichste Indiz für die (Nicht-)Benutzung des Fernsehers ist die Bedienung! Es reicht zu beobachten, ob der Verseher aktiv genutzt wird, sprich: ob man den Sender wechselt, die Lautstärke verändert oder einfach nur wahllos auf der Fernbedienung herumdrückt. Ein IR-Empfänger mit Tageslicht- und 38kHz-Filter liegt noch herum, also anschließen und gucken, was passiert. Der Einfachheit halber hängt das Teil am Interrupt-Eingang des AVR. Beim auslösen wird ein Zähler gesetzt und per Timer langsam heruntergezählt. Damit die Glotze nicht an der spannensten Stelle eines längeren Films einfach ausgeht, blinkt in den letzten 15 Minuten eine LED. Diese wird auch beim Auslösen des Interrupts des IR-Empfängers kurz aktiviert. Beim Herumspielen mit der Schaltung habe ich jedoch eine Feststellung gemacht: ab und zu reagiert der Empfänger auch auf andere Lichteinflüsse (oder er hat einfach nur einen Knall) und gibt einen kurzen Impuls ab. Der Puls reicht aus, um den Timer wieder zurückzusetzen, also sehr ungeschickt. ==Filter== Ein Filter muss her. Da ich keine größere Lust hatte und gleichzeitig mit meinem DSO spielen wollte, wurde er heuristisch aufgebaut. Mehr oder weniger wahllos Bauteile gesetzt, bis das herauskam, was ich wollte. [[Bild:Panasonic_filter.png]] Kurz zur Funktionsweise: R1 zieht den Ausgang OpenCollector-Ausgang des IR-Empfängers auf 5V, gleiches macht R3 mit dem Elko. Hat der Empfänger ein Signal erkannt, zieht er seinen Ausgang auf Low und dadurch die Spannung am Elko auf etwa 0,7V (bedingt durch die Diode). Die Diode bewirkt, dass der Kondensator nur durch den 10k-Widerstand (und nicht auch durch R1 und R2) geladen wird. R2 kann man bei entsprechender Wahl von R1 auch weglassen - nachdem es so aber recht gut klappte: never change a running system ;) <gallery> Bild:Panasonic_fb.png|Gefiltertes Signal einer Fernbedienung Bild:Panasonic_stoerung.png|Störung am Empfänger </gallery> CH1 (cyan) ist jeweils das "gefilterte" Ausgangssignal, CH2 (gelb) das, was vom Empfänger kommt. Die blauen Linien sind stehen für die Spannung, ab der der AVR eine Eingangsspannung als Low-Pegel erkennt. Beim Empfang einer Fernbedienung sieht man, dass die Spannung zuverlässig unterschritten wird. Im rechten Bild wurde mit einem Laserpointer mit hohem IR-Anteil das Auslösen provoziert beim ersten Schalten des Empfängers wäre der Timer bereits zurückgesetzt worden, durch die Entladekurve, bleibt die Spannung allerdings noch über dem Ansprechwert. Bei der zweiten Störung, die ich empfangen habe, löste die Schaltung gerade so nach knapp 9ms aus. Allerdings ist auch der Spannungspegel vor der erneuten Störung zu beachten: durch die vorhergehende Spitze wurde der Kondensator schon ein Stück entladen, eine Auslösung fällt bei nachfolgenden Signalen also leichter. =Schaltung= So schauts aus: <gallery> Bild:Panasonic_sch.png|Stromlaufplan Bild:Panasonic_brd.png|Board (optimiert für Lochraster) Bild:Panasonic_real.jpg|Aufbau in Natura Bild:Panasonic_fuses.png|Fuses im ATtiny13 (H:0xF9, L:0x7A) </gallery> =Download= [[Datei:PanasonicOff.zip]] C-Code und EAGLE-Dateien =Nachtrag= Das Teil hat ein riesengroßes Problem, das den Spareffekt zunichte machen kann: Schaltet man den Fernseher per Fernbedienung ab, wird dies natürlich auch getriggert. Nach der voreingestellten Zeit wird dann wieder der Power-Befehl gesendet. Problem an der Sache: Zumindest unser Panasonic lässt sich per Power-Knopf auf der Fernbedienung sowohl aus- als auch einschalten. Wenn es dumm läuft, ist die Flimmerkiste nach abgelaufener Zeit wieder an (und geht dann ohne Zutun auch nicht wieder aus). Gleiches passiert natürlich auch, wenn der Empfänger längerfristig gestört wird und somit versehentlich getriggert wird. Lösung: Wenn man sieht, dass die Standby-LED leuchtet: mechanisch abschalten. Technisch gäbe es für das Problem mehrere Lösungen: * Schalt- oder Videosignal vom SCART verwenden, um den Betriebszustand zu ermitteln * Stromverbrauch der Kiste messen (z. B. mit Spule um die Zuleitung) * Temperatur am Gehäuse messen Da ich jedoch auf die technischen Lösungen zurückgreife, landet die Schaltung zusätzlich in der Kategorie Murks. [[Category:AVR]] [[Category:Murks]] 6da927dae818ade2f474c02b43d3e847bbedbbed 490 468 2010-08-07T12:13:59Z Chris 2 wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny13 | Takt = 9,6 | FuseH = F9 | FuseL = 7A }} Mein Vater hat, wie viele, die Angewohnheit, vor dem Fernseher einzuschlafen. Soweit nicht schlimm, allerdings geht es auf Dauer unnötigerweise auf die Stromrechnung und die Flimmerkiste wird dadurch auch nicht jünger. Manchmal kommt noch jemand am Wohnzimmer vorbei und schaltet das Gerät ab. Das muss doch auch einfacher gehen... =Ideen= Meine erste Idee war, dem Teil per Zeitschaltuhr zumindest für eine Minute pro Nacht den Saft abzudrehen. Anders als unser alter Telefunken geht der Panasonic nach Spannungsrückkehr _nicht_ in den Stand-By. Genauso ist ihm die 12V-Steuerspannung am Scart grundsätzlich egal, sodass man selbes Spiel mit dem SAT-Receiver treiben könnte. Die zweite Idee war (auch noch vor dem Erlangen von Kenntnissen in der µC-Programmierung) war, eine Universal-Fernbedienung mit einem Wecker zu verheiraten. Blöd nur: Der Wecker schaltet seinen Alarmkontakt für einige Minuten, die Fernbedienung wird also unnötig lange betätigt, die Batterien gehen schnell leer und man hat eine Aperatur, die zwei Mal am Tag die Glotze abdreht und gleichzeitig die Fernbedienung zum wiederanschalten in dieser Zeit blockiert. Das hat weder [http://de.wikipedia.org/wiki/Woman_acceptance_factor WAF] noch <span title="father acceptance factor">FAF</span>. Das mit der Universal-Fernbedienung habe ich daher auch relativ schnell verworfen, die Idee mit dem Wecker blieb noch eine Weile. =Die Lösung= Der nächste Ansatz war, die Fernbedienung in einem Mikrocontroller nachzubilden. Seit dem [http://ladyada.net/make/tvbgone/ TV-B-Gone] ist das massenhafte Abschalten von TV-Geräten ein Geek-Volkssport geworden. Ein guter Ansatz. Als nächstes schaute ich mir die [http://lirc.sourceforge.net/remotes/ Fernbedienungs-Bibliothek von LIRC] an. Von Panasonic gibt es genügend Codes. Allerdings keinen, der (auf den ersten Blick) exakt auf die Fernbedienung hier passt. Also: Fototranse an die Soundkarte anklemmen, aufnehmen ([[Datei:Panasonic.wav]]) und genauer anschauen (z. B. mit [http://audacity.sourceforge.net/ Audacity]). Netterweise war die Soundkarte lahm und übersteuert genug, dass man keinen 38kHz-Filter auf die Aufnahme anwenden musste (an den Flanken sieht man noch ein bisschen was). Mit Papier und Bleistift habe ich dann das Protokoll analysiert und vollständige Übereinstimmung zu einer Definition von LIRC gefunden. Muss das Signal nur noch nachgebaut werden. Die Ausgabe der Bytes ist kein Problem, nur das Trägersignal von 38kHz macht mir etwas Sorgen. Zwar kann man dies auch mit C halbwegs gut zu Fuß ausgeben, muss aber beim Timing etwas aufpassen. Netterweise kann man selbst mit dem sonst recht schwachen ATtiny13 hardwareseitig Signale mit einem Rechteck moduliert ausgeben. Spart man sich einen NE555 bzw. nervige Timinganpassungen. Den Code hierfür habe ich auch beim TV-B-Gone wiederentdeckt. Nachdem der Fernbedienungscode dem Mikrocontroller beigebracht und das Timing noch ein bisschen angepasst wurde (kommt auf 99% an das Original heran), ging die Überlegerei wieder los: wie auslösen? Hier kommt der Wecker wieder ins Spiel: Statt meinen Vater zu wecken (damit er den Fernseher abstellt), kann der doch die Stromversorgung schalten. Blöd auch hier wieder: Zwei Spannungsquellen, weil der AVR halbwegs genau 5V sehen will, da sonst der RC-Taktgeber einen zu niedrigen Takt ausgibt und von der IR-LED nur noch Kauderwelsch kommt. Außerdem sind Wecker unerhört teuer - da lohnt es sich schon fast, eine RTC samt Display an den kleinen anzuschließen. Totaler Overkill ==Die bessere Lösung== Irgendwann fiel es mir wie Schuppen von den Augen: Das deutlichste Indiz für die (Nicht-)Benutzung des Fernsehers ist die Bedienung! Es reicht zu beobachten, ob der Verseher aktiv genutzt wird, sprich: ob man den Sender wechselt, die Lautstärke verändert oder einfach nur wahllos auf der Fernbedienung herumdrückt. Ein IR-Empfänger mit Tageslicht- und 38kHz-Filter liegt noch herum, also anschließen und gucken, was passiert. Der Einfachheit halber hängt das Teil am Interrupt-Eingang des AVR. Beim auslösen wird ein Zähler gesetzt und per Timer langsam heruntergezählt. Damit die Glotze nicht an der spannensten Stelle eines längeren Films einfach ausgeht, blinkt in den letzten 15 Minuten eine LED. Diese wird auch beim Auslösen des Interrupts des IR-Empfängers kurz aktiviert. Beim Herumspielen mit der Schaltung habe ich jedoch eine Feststellung gemacht: ab und zu reagiert der Empfänger auch auf andere Lichteinflüsse (oder er hat einfach nur einen Knall) und gibt einen kurzen Impuls ab. Der Puls reicht aus, um den Timer wieder zurückzusetzen, also sehr ungeschickt. ==Filter== Ein Filter muss her. Da ich keine größere Lust hatte und gleichzeitig mit meinem DSO spielen wollte, wurde er heuristisch aufgebaut. Mehr oder weniger wahllos Bauteile gesetzt, bis das herauskam, was ich wollte. [[Bild:Panasonic_filter.png]] Kurz zur Funktionsweise: R1 zieht den Ausgang OpenCollector-Ausgang des IR-Empfängers auf 5V, gleiches macht R3 mit dem Elko. Hat der Empfänger ein Signal erkannt, zieht er seinen Ausgang auf Low und dadurch die Spannung am Elko auf etwa 0,7V (bedingt durch die Diode). Die Diode bewirkt, dass der Kondensator nur durch den 10k-Widerstand (und nicht auch durch R1 und R2) geladen wird. R2 kann man bei entsprechender Wahl von R1 auch weglassen - nachdem es so aber recht gut klappte: never change a running system ;) <gallery> Bild:Panasonic_fb.png|Gefiltertes Signal einer Fernbedienung Bild:Panasonic_stoerung.png|Störung am Empfänger </gallery> CH1 (cyan) ist jeweils das "gefilterte" Ausgangssignal, CH2 (gelb) das, was vom Empfänger kommt. Die blauen Linien sind stehen für die Spannung, ab der der AVR eine Eingangsspannung als Low-Pegel erkennt. Beim Empfang einer Fernbedienung sieht man, dass die Spannung zuverlässig unterschritten wird. Im rechten Bild wurde mit einem Laserpointer mit hohem IR-Anteil das Auslösen provoziert beim ersten Schalten des Empfängers wäre der Timer bereits zurückgesetzt worden, durch die Entladekurve, bleibt die Spannung allerdings noch über dem Ansprechwert. Bei der zweiten Störung, die ich empfangen habe, löste die Schaltung gerade so nach knapp 9ms aus. Allerdings ist auch der Spannungspegel vor der erneuten Störung zu beachten: durch die vorhergehende Spitze wurde der Kondensator schon ein Stück entladen, eine Auslösung fällt bei nachfolgenden Signalen also leichter. =Schaltung= So schauts aus: <gallery> Bild:Panasonic_sch.png|Stromlaufplan Bild:Panasonic_brd.png|Board (optimiert für Lochraster) Bild:Panasonic_real.jpg|Aufbau in Natura Bild:Panasonic_fuses.png|Fuses im ATtiny13 (H:0xF9, L:0x7A) </gallery> =Download= [[Datei:PanasonicOff.zip]] C-Code und EAGLE-Dateien =Nachtrag= Das Teil hat ein riesengroßes Problem, das den Spareffekt zunichte machen kann: Schaltet man den Fernseher per Fernbedienung ab, wird dies natürlich auch getriggert. Nach der voreingestellten Zeit wird dann wieder der Power-Befehl gesendet. Problem an der Sache: Zumindest unser Panasonic lässt sich per Power-Knopf auf der Fernbedienung sowohl aus- als auch einschalten. Wenn es dumm läuft, ist die Flimmerkiste nach abgelaufener Zeit wieder an (und geht dann ohne Zutun auch nicht wieder aus). Gleiches passiert natürlich auch, wenn der Empfänger längerfristig gestört wird und somit versehentlich getriggert wird. Lösung: Wenn man sieht, dass die Standby-LED leuchtet: mechanisch abschalten. Technisch gäbe es für das Problem mehrere Lösungen: * Schalt- oder Videosignal vom SCART verwenden, um den Betriebszustand zu ermitteln * Stromverbrauch der Kiste messen (z. B. mit Spule um die Zuleitung) * Temperatur am Gehäuse messen Da ich jedoch nicht auf die technischen Lösungen zurückgreife, landet die Schaltung zusätzlich in der Kategorie Murks. [[Category:AVR]] [[Category:Murks]] 5169ce45c2fca91a40789537768850091e748d48 SNES-Joypad 0 35 469 444 2010-07-08T19:02:25Z Chris 2 Fuses angepasst wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = DD | FuseL = E1 | FuseE = FF }} Als Kind hatte ich mir mal (ja, aus eigener Tasche) einen Super Nintendo gekauft. Nachdem er die Jahre leider nicht überlebt hat und ich doch ab und an mal ein bisschen Verlangen nach SNES habe, griff ich auf Emulatoren für den PC zurück. So gut die Programme auch sind - man hat ein Problem: man muss auf der Tastatur spielen. Das mag bei manchen Spielen noch gehen, wenn man jedoch in brenzliche Situationen kommt, braucht man dann doch die etwas trainierteren Daumen. Irgendwann kam ich auf die Idee, einfach das Gamepad an den PC anzuschließen. Mit einem Nachbau eines SNES-Gamepads, das ich mal geschenkt bekommen habe, funktionierte das ziemlich gut. Im Pad selbst waren zwei CD4021 (Schieberegister) verbaut. Die Funktionsweise des Gamepads ist somit genauso simpel wie... simpel. Wenn die CPU in der Konsole den Controller auslesen will, werden die Daten per Latch in das Register geladen, von wo es dann seriell ausgelesen werden kann. [[Bild:SNES-stecker.jpg|thumb|Anschlussbelegung am Stecker]] Die Beschaltung im Controller ist folgendermaßen: {| ! Pin|| Farbe || Funktion |- | 1 || braun || GND |- | 2 || rot || Data |- | 3 || orange || Latch |- | 4 || gelb || Clock |- | 5 || weiß || Vcc |} Bei meiner ersten Entwicklung war das Gamepad am Parallel-Port angeschlossen und wurde von einem kleinen VB-Programm ausgelesen. Die Tastenanschläge wurden dann per DLL als Tastatur-Eingaben simuliert. Das ganze hatte nur ein paar Nachteile: * Die Software war nicht besonders schön * Der Parallelport wurde (mal wieder) zweckentfremdet * Man muss hinter den PC kriechen, wenn man wieder etwas drucken will * Das Ganze ist einfach nicht rund (vorangegangene Punkte) * Mein Notebook hat weder eine parallele noch serielle Schnittstelle Irgendwann entdeckte ich [http://www.obdev.at/products/vusb/index-de.html V-USB], eine Software-Implementierung von USB in AVRs. Als Projekt war [http://www.raphnet.net/electronique/snes_nes_usb/index_en.php SNES/NES gamepad (and mouse) to USB adapter] verlinkt. Die Schaltung habe ich mir dann relativ zügig aufgebaut, um zu testen, ob da wirklich das dahintersteckt, was ich mir erwartet hatte. Tatsächlich meldete Windows 2s nach dem Einstecken der Konstruktion eine neue Hardware. Nur die Tatsache, dass an einem 28-Pin-Mikrocontroller nur ca. 10 Pins und auf den 8KB Speicher nur 3 belegt waren und das Ganze nicht richtig im Gamecontroller untergebracht werden konnte, störte mich ein wenig. Vor kurzem las ich dann folgendes auf obdev.at: <pre> New: Internal RC Oscillator Supported AVR-USB supports the internal RC oscillator of all AVRs with internal high frequency PLL, such as the ATTiny45 or ATTiny26. No external crystal is needed on these devices! See the EasyLogger example for details. </pre> Das war das, worauf ich gewartet hatte: Der ATTiny45 hat 8 Beine, wofür 2 für USB und weitere 3 für die Standardbeschaltung verwendet werden. Somit bleiben genau die benötigten drei Anschlüsse für das Gamepad frei. Die Beispielanwendung für die Implementierung ([http://www.obdev.at/products/avrusb/easylogger.html EasyLogger]) zielt schon sehr gut in die Richtung, in die ich gehen will. Der Großteil des Quelltextes konnte beibehalten werden, Teile kamen von Raph und wurden ziemlich stark umgebaut. Nachdem ich einige Wochen zuvor kläglich daran gescheitert bin, die Software von oben auf den ATTiny2313 zu portieren, nahm ich mir zum Ziel, den Quelltext so klein wie möglich zu gestalten. Nach etlichen Optimierversuchen und Brennvorgängen war es dann geschafft: Das kompilierte Programm ist exakt 2000 Byte groß. Leider hat der Device-Name etwas darunter gelitten - es ist allerdings noch deutlich erkennbar, worum es sich handelt. Ein weiteres Ziel war, die Elektronik im Controller unterzubringen, sodass nur noch ein USB-Kabel ohne weitere Elektronik am PC angeschlossen wird. Netterweise ist im Gamepad ziemlich viel Platz vorhanden, welcher erlaubt, selbst einen DIP-IC aufgelötet auf einer Platine zu fassen. Also flugs die Schaltung vom Steckbrett auf die Platine bringen. Nach dem ersten Test am PC war ich etwas irritiert: kein fröhliches "Plüm-Plim" vom PC, stattdessen kam nach einigen Wartesekunden ein "Plopp" aus den Lautsprechern: "Hardware wurde nicht erkannt". IC ausgelötet und wieder aufs Steckbrett: "Plüm-Plim" (Hardware erkannt). Auch nach langem Suchen war kein Fehler in der Schaltung zu finden. Also zurück an den Anfang: [[PLL im ATTiny45 kalibrieren]]. [[Bild:SNES-einbau.jpg|thumb|Einbau des V-USB-Controllers im SNES-Gamepad]] Nach ein paar Versuchen klappte es auch und ich konnte das Gamepad wieder schließen. Wenn mich jetzt die Lust packt heißt es nur noch Controller vorne am PC an einem freien USB-Port anschließen und losspielen. Da der Aufbau auf Lochraster zwar "ganz nett" ist, aber noch nicht der Weisheit letzter Schluss ist, habe eine kleine Schaltung + Platine in SMD in EAGLE erstellt: <gallery> Bild:Snes-usb_sch.png|Stromlaufplan Bild:SNES-brd.png|SMD-Layout der Schaltung Bild:Snes-usb-2313_sch.png|Stromlaufplan der ATtiny2313-Version </gallery> Die Schaltung ist zwar nicht gerade ideal zum Brennen des AVRs, aber evtl. könnte es klappen, wenn man die Anschlüsse für USB (oben) und für den SNES-Controllers (unten) ausnutzt. Leider kommt man nicht 'drum, einen Draht direkt an RESET zu löten. Platz für einen Testpin ist leider nicht mehr vorhanden. Die Anschlussbelegungen sind jeweils nach den Standards. Auf der SNES-Seite wie oben angegeben, auf USB-Seite so wie im USB-Standard angegeben (Näheres ist dem Stromlaufplan in der ZIP-Datei zu entnehmen). = Downloads = Die Firmware ist unkompiliert, da der OSCCAL-Wert nicht automatisch ermittelt wird. Weiterhin wurde kein Kompilat beigelegt, da das verwendete VID/PID-Paar (siehe usbconfig.h) nicht mir gehört und von jedem, der die Hardware einsetzt durch sein Paar ersetzt werden muss. (Wenn man die Schaltung für sich daheim privat betreibt, sollte es jedoch keine Probleme geben) *[[Datei:SNES-USB.zip]] Firmware OHNE automatische Kalibrierung *[[Datei:SNES-USB-autocal.zip]] Firmware MIT automatischer Kalibrierung und Hex-Datei *[[Datei:Snes-usb-2313.zip]] Firmware für ATtiny2313 == Nachtrag (07/2009) == Das Kalibrieren des PLLs kann seit einiger Zeit wegfallen - es gibt nun die Möglichkeit, die PLL anhand der USB-Framelänge beim Anschließen der USB-Devices zu kalibrieren. Habe es selber schon erfolgreich getestet. Näheres dazu: [http://vusb.wikidot.com/examples#toc4 Clocking the AVR from the RC oscillator with auto-calibration]. Achtung: DIE FIRMWARE IN SNES-USB.zip HIER ENTHÄLT DIESES FEATURE NOCH NICHT! ===Nachtrag (03/2010)=== Ich habe jetzt zusätzlich die Firmware für den ATtiny2313 und die für den ATtiny45 mit automatischer Kalibrierung der PLL hochgeladen. Am Notebook meiner Schwester gab es mit angeschlossenem Gamepad mit Autocal-Firmware ein paar Bluescreens. Ob diese tatsächlich von der Firmware ausgelöst wurde, kann ich nicht mit absoluter Sicherheit sagen. Ich weise einfach mal auf den [[Hobbyelektronik.org:Über_Hobbyelektronik.org#Haftungsausschluss|Haftungsausschluss]] hin. [[Category:PC]] [[Category:AVR]] [[Category:USB]] 72b0a32e8037ab4b6881b3fd785c423f15beb73c Datei:Hitz3.png 6 146 474 2010-07-09T20:28:10Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Hitz4.png 6 147 475 2010-07-09T20:28:23Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Hitz5.png 6 148 476 2010-07-09T20:28:28Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Templog.zip 6 149 477 2010-07-09T20:38:49Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Hitzboard.jpg 6 150 478 2010-07-09T20:49:08Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nokia-lcd back.jpg 6 151 481 2010-07-15T14:17:56Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nokia-lcd brd.png 6 152 482 2010-07-15T14:18:08Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nokia-lcd front.jpg 6 153 483 2010-07-15T14:18:24Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nokia-lcd front2.jpg 6 154 484 2010-07-15T14:18:35Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nokia-lcd sch.png 6 155 485 2010-07-15T14:18:50Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 488 485 2010-07-15T14:42:21Z Chris 2 hat eine neue Version von „[[Datei:Nokia-lcd sch.png]]“ hochgeladen:&#32;Bisschen kleiner reicht auch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nokia-lcd.zip 6 156 486 2010-07-15T14:29:55Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Nokia 5110 Displayadapter 0 157 487 2010-07-15T14:36:08Z Chris 2 Seite erstellt (dieses Mal im ersten Anlauf mit Kategorie! ;-)) wikitext text/x-wiki [[Datei:Nokia-lcd_front2.jpg|thumb|Fertig aufgebaut]] Vor einiger Zeit habe ich in der Bucht ein paar Nokia 5110-Displays erstanden. Diese haben mehrere Vorteile: * Günstig (lagen "damals" bei nichtmal 3 Euro) * Gut verfügbar (ok, mittlerweile nicht mehr) * Kompakt * Einfach anzusteuern (PCD8544) Leider war die Hälfte der erhaltenen ziemlich zerkratzt. Der Händler stellte sich ziemlich quer und war nicht zum Austausch bereit. Schlussendlich war es mir dann doch zu blöd, wegen den paar Euro ewig rumzutun. Dafür gab es dann halt eine negative Bewertung ;) Wie dem auch sei, die Displays haben eine Besonderheit, wenn man es so nennen will: Das Display wird auf die Trägerplatine aufgeklipst, die Kontaktierung findet per Leitgummi statt. Zum Basteln muss also eine Adapterplatine her. Woher die Library für das Display herkommt, weiß ich leider nicht mehr. Um Lötbrücken bei den Kontaktierpads des Displays zu vermeiden, habe ich selbige etwas schmaler gemacht. Die Kontakte sollten auf jeden Fall verzinnt werden, da das Kupfer u. U. recht schnell oxidiert und somit an Leitfähigkeit verliert. Zur Beleuchtung dienen, wie beim Display vorgesehen, 6 LEDs. Diese sind bei meinem Adapter in 3 Strängen ausgeführt. Möchte man die Schaltung komplett mit 3,3V betreiben (was für das LCD erforderlich ist) klappts hier leider nur mit roten LEDs. Für grüne oder gar weiße braucht man eine deutlich höhere LED-Spannung. Aus diesem Grund (und um die Hintergrundbeleuchtung abzuschalten, wenn sie nicht benötigt wird) sind die Anoden der LEDs extra herausgeführt. Um das Layout einseitig zu halten, sind die Kathoden der Stränge mit GND der restlichen Schaltung verbunden. Zusätzlich ist auf dem Board Platz für drei Printtaster vorgesehen. Praktisch daran: Das Package der vorgesehenen Kurzhubtaster ist fast genauso hoch wie das Display. Verwendet man die Taster mit etwas höheren Köpfen, kann man die Platine direkt hinter die Gehäusefront bauen und benötigt keine weiteren Tastenköpfe. Zur Befestigung gibt es zwei Möglichkeiten: entweder mit 2mm großen Schrauben (für M2 müssen die Löcher noch ein kleines Stück größer sein!) oder mit zwei zusätzlichen Lötstiften zwischen den Tastern (auf den Fotos noch nicht vorhanden). Die Löcher sind jeweils im 2,54mm-Raster angebracht - somit ist auch die Montierung auf Lochraster kein Problem. Damit das Display auf die Platine passt, muss das Material 0,5mm dick sein oder an den Haltelaschen dünner gemacht werden. Da ich "normales" FR4-Material hatte, wurde mit dem Dremel entsprechend heruntergeschliffen: [[Datei:Nokia-lcd_back.jpg|200px]] Dadurch, dass das LCD durch die Löcher in der Platine positioniert werden, ist die Einfrästiefe von den Seiten nicht allzu kritisch. Sollte man zu viel abgetragen haben, können die Laschen noch ein Stück zurechtgebogen werden. Allerdings ist ein bisschen mehr Überstand besser zu kompensieren (und der Anpressdruck ist ein wenig höher) So sieht der Rest aus: <gallery> Datei:Nokia-lcd_sch.png|Stromlaufplan Datei:Nokia-lcd_brd.png|Board Datei:Nokia-lcd_front.jpg|Board in Natura </gallery> Die violetten Streifen im zweiten Bild stellen Klebestreifen dar, da der Rahmen an diesen Stellen fast auf den Leiterbahnen aufliegt und es dadurch zu Kurzschlüssen kommen kann. Wird die Platine nicht lackiert, sind die Streifen Pflicht! = Download = [[Datei:Nokia-lcd.zip]] [[Kategorie:LCD]] 91d5f876941ddb35503e9dec00fa0ad4da49d632 Datei:Buchsenleiste-knips.jpg 6 158 491 2010-08-09T11:08:15Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Buchsenleisten.jpg 6 159 492 2010-08-09T11:08:27Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Buchsenstifte.jpg 6 160 493 2010-08-09T11:08:33Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Netioshield brd.png 6 161 494 2010-08-09T11:08:41Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Netioshield kontakt.jpg 6 162 495 2010-08-09T11:08:55Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Netioshield.zip 6 163 496 2010-08-09T11:08:59Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Netioshield pwr.png 6 164 497 2010-08-09T11:09:04Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Netioshield pwr brd.png 6 165 498 2010-08-09T11:09:09Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 AVR-NET-IO-Shield 0 166 499 2010-08-09T11:18:33Z Chris 2 Seite erstellt wikitext text/x-wiki Seit einiger Zeit bietet Pollin mit dem [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] ein schönes Einsteigerboard für Netzwerkanwendungen an. Da es fast vollständig kompatibel zu Ulrich Radigs [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex Experimentier-Board] ist, lädt es zum Basteln und erweitern ein. Da das Board aufgrund des Preises und des einfachen Aufbaus recht beliebt ist, bietet Pollin mittlerweile auch ein Erweiterungsboard an. Leider hat das Original-Board und das Erweiterungsboard ein paar Schwachstellen: * Ineffiziente Stromversorgung (7805 und LM317) * Keine Absicherung gegen Kurzschlüsse/Überlast * Höherer Platzbedarf durch Erweiterungen (Grundfläche) * Lange Verbindungen zum Erweiterungsboard * Kein Platz für eigene Ideen Vor allem der erste und letzte Punkt haben mich etwas gestört. = Das Sandwich = [[Datei:Netioshield brd.png|thumb|Das Shields]] Inspiriert von den vielen Erweiterungen (Shields) des [http://arduino.cc/ Arduino] habe ich mich entschieden, eine Erweiterungsplatine im Sandwich-Stil zu entwerfen. Dieses soll direkt auf das Board des NET-IO gesteckt werden können und möglichst alle verfügbaren Pins für eigene Anwendungen zur Verfügung stellen. Die größte Schwierigkeit war, die korrekten Positionen der Bauteile zu finden. Dummerweise habe ich nach dem Bestellen des Bausatzes nicht daran gedacht, die Platine zu scannen. Mit Hilfe der Bauanleitung (die das Board leider nur verzerrt enthält), war es jedoch möglich, die Positionen halbwegs genau herauszufinden. Der optische Vergleich beider Boards und Aufdrücken der Platine auf einen Ausdruck war vielversprechend, absolute Klarheit kann aber nur eine produzierte Leiterkarte bringen. = Verbindung = Weitaus problematischer als das Layout zu zeichnen war das Finden passender Verbinder zwischen den Boards. Mein erster Gedanke war, beim DSub-25 einen stehenden Printstecker auf dem NET-IO und eine stehende Buchse auf dem Shield zu verbauen. Dadurch entsteht zwischen den Platinen allerdings ein Abstand von 20mm. Dazu kommt noch die mechanische Belastung beim Auseinanderziehen. Freiwillig macht man das nicht oft. Irgendwann kam ich auf die eigentlich naheliegende Idee, einen "normalen" Print-Steckverbinder zu nehmen und zum Verbinden der Boards zwei Buchsen für Flachbandkabel zu verwenden. Dadurch wird das Ganze zwar etwas länger, die mechanische Belastung beim Stecken wird aber minimiert. Als nächstes kommen die zwei Stiftleisten EXT und ISP. Normale Buchsenleisten sind zu kurz, um die Platinen zu verbinden. Meine Lösung war, kurze Kontaktbuchsen (SPL 64 bei Reichelt) auf die Buchsenleisten (8,5mm, BL 2x36G 2,54 bei Reichelt) zu stecken. Zusammen mit 15mm langen Abstandsbolzen zwischen den Platinen stehen die Stiftleisten noch einen knappen Millimeter beim Shield hinaus. Perfekt! Da es bei den übrigen Kontakten (unterhalb des AVR, UART und Stromversorgung) keine Stiftleisten "vorinstalliert" sind, bietet sich ein wenig Bastelei an. Wer großzügig die Preisangabe im Katalog abdeckt, kann bei Reichelt AW 226/20 und AW 122/20 bestellen. Alle anderen sollten lange Buchsenleisten möglichst mit gedrehten Kontakten (hat Reichelt nicht!) und Kontaktbuchsen (SPL 64 von Reichelt) haben: Zuerst muss man die Kontakte vom Plastik befreien. Wer nichts zum Auflösen des Kunststoffs zu Hause hat: Einfach an den Anrissen auseinanderzwicken, dadurch können die Kontakte besser herausgepult werden. Anschließend zwei kurze und einen langen Kontakt aufeinanderstecken, optional verlöten und in Schrumpfschlauch verpacken, fertig sind die Verbinder: <gallery> Datei:Buchsenleisten.jpg|Die verwendeten Leisten Datei:Buchsenleiste-knips.jpg|Auseinanderknipsen der Buchsenleisten Datei:Buchsenstifte.jpg|"Gewonnene" Stifte Datei:Netioshield kontakt.jpg|Zusammengesteckt und im verbauten Zustand </gallery> In die andere Platine muss dann nur noch ein Pin aus einer Stiftleiste. Am einfachsten geht es, wenn man alles zusammensteckt, zwischen die Platinen klemmt und mit wenig Zinn verlötet. Wenig Lötzinn deshalb, da sonst die Buchse gleich mit verlötet wird. Wer die beiden Platinen nicht mehr voneinander lösen will, kann auch einfach Drähte einsetzen. In diesem Fall ist es jedoch sehr empfehlenswert, einen zuverlässigen Bootloader zu verwenden oder die ISP-Pins freizuhalten bzw. zur Programmierung verwendbar zu schalten. = Stromversorgung = Mit dem Sandwich-Board war das Problem der Stromversorgung allerdings noch nicht erledigt. Die Wahl fiel auf die einfach (und für 5 sowie 3,3V gleichermaßen) erhältlichen [http://www.national.com/mpf/LM/LM2574.html LM2574]. Dieser braucht zwar aufgrund seiner vergleichsweise niedrigen Schaltfrequenz relativ große Induktivitäten, ist dafür aber ziemlich handzahm. Bei einer Versorgungsspannung von 12-16V sind bei beiden Wandlern lt. Datenblatt Induktivitäten mit 330µH gut geeignet. Um bei den Schaltreglern etwas an Bauhöhe zu sparen, kommen SMD-Spulen zum Einsatz. Aufgrund der großen Flächen ist ein Lötkolben mit >=80W und großer Lötspitze mehr als ratsam! Folgende Bauteile können auf dem NET-IO durch den Umbau weggelassen werden: D1, D2, D3, D4, D5, C1, C2, C3, C5, IC1, IC2, R1, R2 <gallery> Datei:Netioshield pwr brd.png|thumb|Das "Powershield" Datei:Netioshield pwr.png|thumb|überflüssige Bauteile </gallery> = Kollisionen = Beim Planen des eigenen Shields sollte man beim Platzieren von Bauteilen auf dem Bottom-Layer sehr vorsichtig sein, da es sehr schnell zu Kollisionen kommen kann. Insbesondere bei Kondensatoren und Buchsen muss man einen gewissen Abstand einplanen. Über der Netzwerkbuchse sollte man zudem keine bedrahteten Bauteile einsetzen, da die Chance von Kurzschlüssen hier mehr als hoch ist. Auch der Einsatz von SMD-Bauteilen auf der Unterseite des Shields bei der Netzwerkbuchse sollte vermieden werden. = Download = [[Datei:Netioshield.zip]] [[Kategorie:AVR]] 7c93b2ebd79a14f4e11b922881ca428e91c87679 502 499 2010-08-09T11:33:16Z Chris 2 Foto des Spannungswandlers und Info zur Polyfuse hinzugefügt wikitext text/x-wiki Seit einiger Zeit bietet Pollin mit dem [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] ein schönes Einsteigerboard für Netzwerkanwendungen an. Da es fast vollständig kompatibel zu Ulrich Radigs [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex Experimentier-Board] ist, lädt es zum Basteln und erweitern ein. Da das Board aufgrund des Preises und des einfachen Aufbaus recht beliebt ist, bietet Pollin mittlerweile auch ein Erweiterungsboard an. Leider hat das Original-Board und das Erweiterungsboard ein paar Schwachstellen: * Ineffiziente Stromversorgung (7805 und LM317) * Keine Absicherung gegen Kurzschlüsse/Überlast * Höherer Platzbedarf durch Erweiterungen (Grundfläche) * Lange Verbindungen zum Erweiterungsboard * Kein Platz für eigene Ideen Vor allem der erste und letzte Punkt haben mich etwas gestört. = Das Sandwich = [[Datei:Netioshield brd.png|thumb|Das Shields]] Inspiriert von den vielen Erweiterungen (Shields) des [http://arduino.cc/ Arduino] habe ich mich entschieden, eine Erweiterungsplatine im Sandwich-Stil zu entwerfen. Dieses soll direkt auf das Board des NET-IO gesteckt werden können und möglichst alle verfügbaren Pins für eigene Anwendungen zur Verfügung stellen. Die größte Schwierigkeit war, die korrekten Positionen der Bauteile zu finden. Dummerweise habe ich nach dem Bestellen des Bausatzes nicht daran gedacht, die Platine zu scannen. Mit Hilfe der Bauanleitung (die das Board leider nur verzerrt enthält), war es jedoch möglich, die Positionen halbwegs genau herauszufinden. Der optische Vergleich beider Boards und Aufdrücken der Platine auf einen Ausdruck war vielversprechend, absolute Klarheit kann aber nur eine produzierte Leiterkarte bringen. = Verbindung = Weitaus problematischer als das Layout zu zeichnen war das Finden passender Verbinder zwischen den Boards. Mein erster Gedanke war, beim DSub-25 einen stehenden Printstecker auf dem NET-IO und eine stehende Buchse auf dem Shield zu verbauen. Dadurch entsteht zwischen den Platinen allerdings ein Abstand von 20mm. Dazu kommt noch die mechanische Belastung beim Auseinanderziehen. Freiwillig macht man das nicht oft. Irgendwann kam ich auf die eigentlich naheliegende Idee, einen "normalen" Print-Steckverbinder zu nehmen und zum Verbinden der Boards zwei Buchsen für Flachbandkabel zu verwenden. Dadurch wird das Ganze zwar etwas länger, die mechanische Belastung beim Stecken wird aber minimiert. Als nächstes kommen die zwei Stiftleisten EXT und ISP. Normale Buchsenleisten sind zu kurz, um die Platinen zu verbinden. Meine Lösung war, kurze Kontaktbuchsen (SPL 64 bei Reichelt) auf die Buchsenleisten (8,5mm, BL 2x36G 2,54 bei Reichelt) zu stecken. Zusammen mit 15mm langen Abstandsbolzen zwischen den Platinen stehen die Stiftleisten noch einen knappen Millimeter beim Shield hinaus. Perfekt! Da es bei den übrigen Kontakten (unterhalb des AVR, UART und Stromversorgung) keine Stiftleisten "vorinstalliert" sind, bietet sich ein wenig Bastelei an. Wer großzügig die Preisangabe im Katalog abdeckt, kann bei Reichelt AW 226/20 und AW 122/20 bestellen. Alle anderen sollten lange Buchsenleisten möglichst mit gedrehten Kontakten (hat Reichelt nicht!) und Kontaktbuchsen (SPL 64 von Reichelt) haben: Zuerst muss man die Kontakte vom Plastik befreien. Wer nichts zum Auflösen des Kunststoffs zu Hause hat: Einfach an den Anrissen auseinanderzwicken, dadurch können die Kontakte besser herausgepult werden. Anschließend zwei kurze und einen langen Kontakt aufeinanderstecken, optional verlöten und in Schrumpfschlauch verpacken, fertig sind die Verbinder: <gallery> Datei:Buchsenleisten.jpg|Die verwendeten Leisten Datei:Buchsenleiste-knips.jpg|Auseinanderknipsen der Buchsenleisten Datei:Buchsenstifte.jpg|"Gewonnene" Stifte Datei:Netioshield kontakt.jpg|Zusammengesteckt und im verbauten Zustand </gallery> In die andere Platine muss dann nur noch ein Pin aus einer Stiftleiste. Am einfachsten geht es, wenn man alles zusammensteckt, zwischen die Platinen klemmt und mit wenig Zinn verlötet. Wenig Lötzinn deshalb, da sonst die Buchse gleich mit verlötet wird. Wer die beiden Platinen nicht mehr voneinander lösen will, kann auch einfach Drähte einsetzen. In diesem Fall ist es jedoch sehr empfehlenswert, einen zuverlässigen Bootloader zu verwenden oder die ISP-Pins freizuhalten bzw. zur Programmierung verwendbar zu schalten. = Stromversorgung = Mit dem Sandwich-Board war das Problem der Stromversorgung allerdings noch nicht erledigt. Die Wahl fiel auf die einfach (und für 5 sowie 3,3V gleichermaßen) erhältlichen [http://www.national.com/mpf/LM/LM2574.html LM2574]. Dieser braucht zwar aufgrund seiner vergleichsweise niedrigen Schaltfrequenz relativ große Induktivitäten, ist dafür aber ziemlich handzahm. Bei einer Versorgungsspannung von 12-16V sind bei beiden Wandlern lt. Datenblatt Induktivitäten mit 330µH gut geeignet. Um bei den Schaltreglern etwas an Bauhöhe zu sparen, kommen SMD-Spulen zum Einsatz. Aufgrund der großen Flächen ist ein Lötkolben mit >=80W und großer Lötspitze mehr als ratsam! Folgende Bauteile können auf dem NET-IO durch den Umbau weggelassen werden: D1, D2, D3, D4, D5, C1, C2, C3, C5, IC1, IC2, R1, R2 <gallery> Datei:Netioshield pwr brd.png|Das "Powershield" Datei:Netioshield power.jpg|Der relevante Part Datei:Netioshield pwr.png|überflüssige Bauteile </gallery> Zur Absicherung dient eine sich selbst rückstellende Polyfuse. Diese muss an die Eingangsspannung angepasst werden, da aufgrund der Schaltregler bei höheren Spannungen ein geringerer Strom fließt. Bei meinen groben Messungen kam die Schaltung auf etwa 1,6W. Bei einer Eingangsspannung von 12V (Spannungsabfall von ca. 1,4V am Gleichrichter beachten!) kann man daher mit einem Strombedarf von 150mA rechnen. Die Polyfuse kann man daher (ungeachtet der Verbraucher auf dem Shield) auf etwa 200mA dimensionieren. = Kollisionen = Beim Planen des eigenen Shields sollte man beim Platzieren von Bauteilen auf dem Bottom-Layer sehr vorsichtig sein, da es sehr schnell zu Kollisionen kommen kann. Insbesondere bei Kondensatoren und Buchsen muss man einen gewissen Abstand einplanen. Über der Netzwerkbuchse sollte man zudem keine bedrahteten Bauteile einsetzen, da die Chance von Kurzschlüssen hier mehr als hoch ist. Auch der Einsatz von SMD-Bauteilen auf der Unterseite des Shields bei der Netzwerkbuchse sollte vermieden werden. = Download = [[Datei:Netioshield.zip]] [[Kategorie:AVR]] c0626ca5c512f8c2d621ef9b511ccdf325dd1016 Datei:Buchsenleisten.jpg 6 159 500 492 2010-08-09T11:19:51Z Chris 2 hat eine neue Version von „[[Datei:Buchsenleisten.jpg]]“ hochgeladen wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Netioshield power.jpg 6 167 501 2010-08-09T11:22:25Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Hauptseite 0 1 503 489 2010-08-09T11:34:35Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *09.08.2010 [[AVR-NET-IO-Shield]] *15.07.2010 [[Nokia 5110 Displayadapter]] *09.07.2010 [[Sommerhitz]] *04.03.2010 [[VBus-Decoder]] *24.02.2010 [[UnitColor]] =Updates= *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) f5e93e162362a1d71509ac36e01f89c6bcc80b4b 508 503 2010-08-30T22:24:16Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *31.08.2010 [[Energieerfassung]] *09.08.2010 [[AVR-NET-IO-Shield]] *15.07.2010 [[Nokia 5110 Displayadapter]] *09.07.2010 [[Sommerhitz]] *04.03.2010 [[VBus-Decoder]] *24.02.2010 [[UnitColor]] =Updates= *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) c5a35d41c26523eb6598d8bad6ea40393da7fff4 521 508 2010-09-01T19:44:55Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *31.08.2010 [[Energieerfassung]] *09.08.2010 [[AVR-NET-IO-Shield]] *15.07.2010 [[Nokia 5110 Displayadapter]] *09.07.2010 [[Sommerhitz]] *04.03.2010 [[VBus-Decoder]] =Updates= *01.09.2010 [[AVR-Doper]] unter Windows 7 *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) e773f28b2870b4ba2b94a2f5c3c4de8adcf1d33d 541 521 2010-10-10T21:07:16Z Chris 2 /* Neues */ wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *10.10.2010 [[Kamertimer]] *31.08.2010 [[Energieerfassung]] *09.08.2010 [[AVR-NET-IO-Shield]] *15.07.2010 [[Nokia 5110 Displayadapter]] *09.07.2010 [[Sommerhitz]] *04.03.2010 [[VBus-Decoder]] =Updates= *01.09.2010 [[AVR-Doper]] unter Windows 7 *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) bedd5989de8ab2983e03b4c841708b2cf7757b5c 542 541 2010-10-10T21:08:04Z Chris 2 /* Neues */ ähmja, heißt natürlich Kameratimer wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *10.10.2010 [[Kameratimer]] *31.08.2010 [[Energieerfassung]] *09.08.2010 [[AVR-NET-IO-Shield]] *15.07.2010 [[Nokia 5110 Displayadapter]] *09.07.2010 [[Sommerhitz]] *04.03.2010 [[VBus-Decoder]] =Updates= *01.09.2010 [[AVR-Doper]] unter Windows 7 *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) 8730f9cab35b7cf052ef3f31306d3ae8c34d810a 544 542 2010-10-10T21:21:08Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *10.10.2010 [[Kameratimer]] *31.08.2010 [[Energieerfassung]] *09.08.2010 [[AVR-NET-IO-Shield]] *15.07.2010 [[Nokia 5110 Displayadapter]] *09.07.2010 [[Sommerhitz]] *04.03.2010 [[VBus-Decoder]] =Updates= *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *01.09.2010 [[AVR-Doper]] unter Windows 7 *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) 72e8d2fce6e28d17f4261ffc06c9256cfc152b7d Energieerfassung 0 168 504 2010-08-30T22:19:35Z Chris 2 Erste (noch sehr unvollständige) Version wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== TODO: Zählerfoto Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[wpde:Ferraris-Zähler Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. TODO: Bisschen bebilderte Werbung?! Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. TODO: Bild vom Zähler mit Streifen Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. TODO: Oszibild Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: TODO: Stromlaufplan Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. TODO: Bild vom Tarifzähler Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. TODO: Schon wieder ein Bild (Relais Stromfreigabe) Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== TODO: Foto des „Großhirns“ In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. TODO: Screenshots ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [wpde:Hamming-Abstand] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= TODO =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Vcc auf GND) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann * [http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller * Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23&paged=2 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] a3c91cc0d02e1b73ed2c84d20638b57ff70327c3 505 504 2010-08-30T22:21:01Z Chris 2 /* Großhirn */ wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== TODO: Zählerfoto Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[wpde:Ferraris-Zähler Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. TODO: Bisschen bebilderte Werbung?! Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. TODO: Bild vom Zähler mit Streifen Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. TODO: Oszibild Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: TODO: Stromlaufplan Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. TODO: Bild vom Tarifzähler Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. TODO: Schon wieder ein Bild (Relais Stromfreigabe) Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== TODO: Foto des „Großhirns“ In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. TODO: Screenshots ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [wpde:Hamming-Abstand] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= TODO =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Vcc auf GND) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann * [http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller * Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23&paged=2 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] 6f0836db540f5b1c68dfd60eee411fec27e36814 506 505 2010-08-30T22:22:30Z Chris 2 /* Energie-Zähler */ wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== TODO: Zählerfoto Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[wpde:Ferraris-Zähler Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. TODO: Bisschen bebilderte Werbung?! Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. TODO: Bild vom Zähler mit Streifen Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. TODO: Oszibild Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: TODO: Stromlaufplan Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. TODO: Bild vom Tarifzähler Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. TODO: Schon wieder ein Bild (Relais Stromfreigabe) Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== TODO: Foto des „Großhirns“ In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. TODO: Screenshots ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= TODO =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Vcc auf GND) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann * [http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller * Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23&paged=2 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] f35e0ec9969788ade4d7ef465263d6f5e8169eec 507 506 2010-08-30T22:23:13Z Chris 2 /* Weblinks/Siehe auch */ wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== TODO: Zählerfoto Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[wpde:Ferraris-Zähler Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. TODO: Bisschen bebilderte Werbung?! Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. TODO: Bild vom Zähler mit Streifen Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. TODO: Oszibild Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: TODO: Stromlaufplan Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. TODO: Bild vom Tarifzähler Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. TODO: Schon wieder ein Bild (Relais Stromfreigabe) Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== TODO: Foto des „Großhirns“ In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. TODO: Screenshots ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= TODO =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Vcc auf GND) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann * [http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller * Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] 73310a39eb6dcdf448464670c5c248fad32f1b06 518 507 2010-08-31T22:04:06Z Chris 2 Fotos hinzugefügt wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== [[Datei:Nrg hauptzaehler.jpg|thumb|Stromzähler mit aufgesetzter Erfassungseinheit]] Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[wpde:Ferraris-Zähler Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. TODO: Bisschen bebilderte Werbung?! Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. TODO: Oszibild Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: TODO: Stromlaufplan Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. [[Datei:Nrg tarifzaehler.jpg|thumb|Tarifzähler, rechts das Fähnchen zum Anzeigen des Tarifs]] Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. [[Nrg_relais_freigabe.jpg|thumb|Relais für die Stromfreigabe, mit LED]] Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. <gallery> Datei:Nrg shield.jpg|Shield des Großhirns Datei:Nrg grosshirn.jpg|Hirn von oben </gallery> ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. <gallery> Datei:Nrg lcd 1.jpg|Home-Screen mit Datum und Uhrzeit Datei:Nrg lcd 2.jpg|Aktueller Stromverbrauch Datei:Nrg lcd 3.jpg|Solardaten: Kollektortemperatur, Pumpenlast und Speichertemp. Datei:Nrg lcd 4.jpg|Debuginfos, Timeouts des TCP/IP-Stacks und Refresh des NTP-Clients </gallery> ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= TODO =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Vcc auf GND) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann * [http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller * Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] 96daa4acbc02fcbf377db4c687682fdfd6d3ab31 528 518 2010-09-01T22:00:02Z Chris 2 /* Stromzähler */ Bilder und ein bisschen Beschreibung wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== [[Datei:Nrg hauptzaehler.jpg|thumb|Stromzähler mit aufgesetzter Erfassungseinheit]] Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[:wpde:Ferraris-Zähler|Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. [[Datei:Bananen Frucht.jpg|thumb|Eine Banane, eisenreich und sehr bekömmlich (cc:by-sa Darkone)]] Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. <gallery> Datei:Nrg zaehler umlauf.png|Ein Umlauf, wie er direkt am Fototransistor gemessen wird Datei:Nrg zaehler rauschen.png|"Grundrauschen" der rotierenden Scheibe (ohne DC-Offset) </gallery> Die Leistungsaufnahme lässt sich anhand der Umlaufzeit wie folgt berechnen: [[Datei:Nrg formel leistung.png]] Setzt man die im Screenshot ermittelten 42.6 Sekunden ein, erhält man eine Leistung von ~1127 Watt. Da die Leistung mit der Zeit exponentiell abnimmt, ist bei hohen Leistungsaufnahmen eine relativ hohe Auflösung der Zeit erforderlich. Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: <gallery> Datei:Nrg zaehler auswert.png|Auswerteschaltung Datei:Nrg zaehler pass.png|Zählersignal vor (blau) und nach (gelb) dem Filter </gallery> Links wird der Fototransistor in Sperrrichtung angeschlossen. Der 1µF-Elko und der nachfolgende 100k-Widerstand stellt einen Hochpass mit nicht näher definierter Grenzfrequenz (WolframAlpha sagt [http://www.wolframalpha.com/input/?i=1%2F%282*Pi*100kOhms*1%C2%B5F%29 1.592Hz]) dar. Die Frequenz ist ist im Hinblick auf [[:wpde:Hochpass:Ordnung]], Bauteiletoleranzen und der Zielfrequenz vermutlich nicht einmal ein Richtwert. Der folgende Hochpass hat eine Grenzfrequenz von ca. 16Hz. Hier gilt das gleiche Vertrauen wie in den Tiefpass. Aber alles kein Problem: Die Werte sind weitestgehend unkritisch. Es sind Umläufe im Millihertz-Bereich (also Umlaufdauern in der Größenordnung Sekunden bis Minuten) zu erwarten. Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. [[Datei:Nrg tarifzaehler.jpg|thumb|Tarifzähler, rechts das Fähnchen zum Anzeigen des Tarifs]] Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. [[Datei:Nrg_relais_freigabe.jpg|thumb|Relais für die Stromfreigabe, mit LED]] Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. <gallery> Datei:Nrg shield.jpg|Shield des Großhirns Datei:Nrg grosshirn.jpg|Hirn von oben </gallery> ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. <gallery> Datei:Nrg lcd 1.jpg|Home-Screen mit Datum und Uhrzeit Datei:Nrg lcd 2.jpg|Aktueller Stromverbrauch Datei:Nrg lcd 3.jpg|Solardaten: Kollektortemperatur, Pumpenlast und Speichertemp. Datei:Nrg lcd 4.jpg|Debuginfos, Timeouts des TCP/IP-Stacks und Refresh des NTP-Clients </gallery> ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= TODO =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Vcc auf GND) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann * [http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller * Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] 162664960524ee00a75149463a1a33cb2d9776e4 530 528 2010-09-01T22:06:35Z Chris 2 /* Bereitstellung der Daten */ wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== [[Datei:Nrg hauptzaehler.jpg|thumb|Stromzähler mit aufgesetzter Erfassungseinheit]] Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[:wpde:Ferraris-Zähler|Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. [[Datei:Bananen Frucht.jpg|thumb|Eine Banane, eisenreich und sehr bekömmlich (cc:by-sa Darkone)]] Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. <gallery> Datei:Nrg zaehler umlauf.png|Ein Umlauf, wie er direkt am Fototransistor gemessen wird Datei:Nrg zaehler rauschen.png|"Grundrauschen" der rotierenden Scheibe (ohne DC-Offset) </gallery> Die Leistungsaufnahme lässt sich anhand der Umlaufzeit wie folgt berechnen: [[Datei:Nrg formel leistung.png]] Setzt man die im Screenshot ermittelten 42.6 Sekunden ein, erhält man eine Leistung von ~1127 Watt. Da die Leistung mit der Zeit exponentiell abnimmt, ist bei hohen Leistungsaufnahmen eine relativ hohe Auflösung der Zeit erforderlich. Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: <gallery> Datei:Nrg zaehler auswert.png|Auswerteschaltung Datei:Nrg zaehler pass.png|Zählersignal vor (blau) und nach (gelb) dem Filter </gallery> Links wird der Fototransistor in Sperrrichtung angeschlossen. Der 1µF-Elko und der nachfolgende 100k-Widerstand stellt einen Hochpass mit nicht näher definierter Grenzfrequenz (WolframAlpha sagt [http://www.wolframalpha.com/input/?i=1%2F%282*Pi*100kOhms*1%C2%B5F%29 1.592Hz]) dar. Die Frequenz ist ist im Hinblick auf [[:wpde:Hochpass:Ordnung]], Bauteiletoleranzen und der Zielfrequenz vermutlich nicht einmal ein Richtwert. Der folgende Hochpass hat eine Grenzfrequenz von ca. 16Hz. Hier gilt das gleiche Vertrauen wie in den Tiefpass. Aber alles kein Problem: Die Werte sind weitestgehend unkritisch. Es sind Umläufe im Millihertz-Bereich (also Umlaufdauern in der Größenordnung Sekunden bis Minuten) zu erwarten. Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. [[Datei:Nrg tarifzaehler.jpg|thumb|Tarifzähler, rechts das Fähnchen zum Anzeigen des Tarifs]] Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. [[Datei:Nrg_relais_freigabe.jpg|thumb|Relais für die Stromfreigabe, mit LED]] Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. <gallery> Datei:Nrg shield.jpg|Shield des Großhirns Datei:Nrg grosshirn.jpg|Hirn von oben </gallery> ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. <gallery> Datei:Nrg lcd 1.jpg|Home-Screen mit Datum und Uhrzeit Datei:Nrg lcd 2.jpg|Aktueller Stromverbrauch Datei:Nrg lcd 3.jpg|Solardaten: Kollektortemperatur, Pumpenlast und Speichertemp. Datei:Nrg lcd 4.jpg|Debuginfos, Timeouts des TCP/IP-Stacks und Refresh des NTP-Clients </gallery> ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== [[Datei:Nrg json.png|thumb|Exemplarischer JSON-Datensatz]] Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= TODO =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Vcc auf GND) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann * [http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller * Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] 62e73bfdc4696beaa1704502e64476abfc4d69a7 543 530 2010-10-10T21:18:17Z Chris 2 /* Solaranlage */ Einsatz für die PT1000! wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== [[Datei:Nrg hauptzaehler.jpg|thumb|Stromzähler mit aufgesetzter Erfassungseinheit]] Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[:wpde:Ferraris-Zähler|Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. [[Datei:Bananen Frucht.jpg|thumb|Eine Banane, eisenreich und sehr bekömmlich (cc:by-sa Darkone)]] Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. <gallery> Datei:Nrg zaehler umlauf.png|Ein Umlauf, wie er direkt am Fototransistor gemessen wird Datei:Nrg zaehler rauschen.png|"Grundrauschen" der rotierenden Scheibe (ohne DC-Offset) </gallery> Die Leistungsaufnahme lässt sich anhand der Umlaufzeit wie folgt berechnen: [[Datei:Nrg formel leistung.png]] Setzt man die im Screenshot ermittelten 42.6 Sekunden ein, erhält man eine Leistung von ~1127 Watt. Da die Leistung mit der Zeit exponentiell abnimmt, ist bei hohen Leistungsaufnahmen eine relativ hohe Auflösung der Zeit erforderlich. Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: <gallery> Datei:Nrg zaehler auswert.png|Auswerteschaltung Datei:Nrg zaehler pass.png|Zählersignal vor (blau) und nach (gelb) dem Filter </gallery> Links wird der Fototransistor in Sperrrichtung angeschlossen. Der 1µF-Elko und der nachfolgende 100k-Widerstand stellt einen Hochpass mit nicht näher definierter Grenzfrequenz (WolframAlpha sagt [http://www.wolframalpha.com/input/?i=1%2F%282*Pi*100kOhms*1%C2%B5F%29 1.592Hz]) dar. Die Frequenz ist ist im Hinblick auf [[:wpde:Hochpass:Ordnung]], Bauteiletoleranzen und der Zielfrequenz vermutlich nicht einmal ein Richtwert. Der folgende Hochpass hat eine Grenzfrequenz von ca. 16Hz. Hier gilt das gleiche Vertrauen wie in den Tiefpass. Aber alles kein Problem: Die Werte sind weitestgehend unkritisch. Es sind Umläufe im Millihertz-Bereich (also Umlaufdauern in der Größenordnung Sekunden bis Minuten) zu erwarten. Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. [[Datei:Nrg tarifzaehler.jpg|thumb|Tarifzähler, rechts das Fähnchen zum Anzeigen des Tarifs]] Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. [[Datei:Nrg_relais_freigabe.jpg|thumb|Relais für die Stromfreigabe, mit LED]] Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. '''Update 10.10.2010:''' Weasel (IRC) ist beim Anblick der Kennlinie der Temperatursensoren in der Anleitung des Vitosolic 200 blitzschnell darauf gekommen, dass es sich um PT500-Elemente handeln müssen, die jedoch nur für sehr teuer Geld erhältlich sind. Mein anfänglicher Scherz vonwegen 2 PT1000 parallel ergibt PT500 hat sich als gar nicht so dumm erwiesen: Idealerweise sind die Widerstände der Sensoren bei gleicher Temperatur ebenfalls gleich, Durch Parallelschaltung zweier PT1000 kann man sie problemlos an der PT1000 betreiben! Da ich sonst nichts mit meinen 9 Sensoren anzufangen wusste, fristen jetzt 8 dieser als 4 Fühler im Keller ihr dasein: Zwei erfassen die Ein- und Auslasstemperatur an der "Primärseite" der Wärmepumpe, einer sitzt im Warmwasserspeicher in oberster Schicht und der 4. misst (da mir noch nichts besseres einfiel) die Raumtemperatur im Heizkeller, die mangels Isolierung der Rohre deutlich zu hoch ist. ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. <gallery> Datei:Nrg shield.jpg|Shield des Großhirns Datei:Nrg grosshirn.jpg|Hirn von oben </gallery> ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. <gallery> Datei:Nrg lcd 1.jpg|Home-Screen mit Datum und Uhrzeit Datei:Nrg lcd 2.jpg|Aktueller Stromverbrauch Datei:Nrg lcd 3.jpg|Solardaten: Kollektortemperatur, Pumpenlast und Speichertemp. Datei:Nrg lcd 4.jpg|Debuginfos, Timeouts des TCP/IP-Stacks und Refresh des NTP-Clients </gallery> ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== [[Datei:Nrg json.png|thumb|Exemplarischer JSON-Datensatz]] Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= TODO =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Vcc auf GND) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann * [http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller * Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] 0895d59594952ade965c4aa8a546ee0707240cc6 Datei:Nrg hauptzaehler.jpg 6 169 509 2010-08-31T21:48:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg lcd 1.jpg 6 170 510 2010-08-31T21:49:00Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg lcd 2.jpg 6 171 511 2010-08-31T21:49:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg lcd 3.jpg 6 172 512 2010-08-31T21:49:14Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg lcd 4.jpg 6 173 513 2010-08-31T21:49:34Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg tarifzaehler.jpg 6 174 514 2010-08-31T21:53:01Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg relais freigabe.jpg 6 175 515 2010-08-31T21:54:27Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg shield.jpg 6 176 516 2010-08-31T21:55:30Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg grosshirn.jpg 6 177 517 2010-08-31T21:59:29Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 AVR-Doper 0 44 519 461 2010-09-01T19:43:33Z Chris 2 Treiber für Windows 7 wikitext text/x-wiki {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = C9 | FuseL = 9F }} Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Ich habe auch damit angefangen, eine SMD-Version der Platine zu machen, allerdings gibt es ein paar Platzprobleme (der ATMega in TQFP ist einfach zu klein für die ganzen Bauteile außen herum). Die Firmware wurde nicht verändert und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download des optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] =AVR-Doper unter Windows 7= Nachdem Windows XP schon etwas betagt ist und Vista eher ein flop war, steht man früher oder später an dem Punkt, Windows 7 zu verwenden. Zwar lassen sich die Vista-Treiber des AVR-Dopers unter Windows 7 installieren, AVR-Studio kann allerdings keine Verbindung zum Doper herstellen. Die Jungs von recursion.jp haben einen Treiber geschrieben, der sowohl unter Win7 x86 und Win7 x64 funktioniert: [http://www.recursion.jp/avrcdc/lowbulk.html] -> "avrcdc_inf.zip" Es kann sein, dass der Treiber manuell signiert werden muss (was bei meiner x86-Installation nicht erforderlich war). Nähere Informationen dazu (und auch der ursprüngliche Hinweis auf den Treiber) befinden sich im [http://forums.obdev.at/viewtopic.php?f=8&t=3591&p=12721#p12721 Forum von Objective Development] [[Category:AVR]] [[Category:USB]] [[Category:PC]] 6bd2f3c912f306d4e1dfb75d11941ef147207507 520 519 2010-09-01T19:44:01Z Chris 2 meh wikitext text/x-wiki {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = C9 | FuseL = 9F }} Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Ich habe auch damit angefangen, eine SMD-Version der Platine zu machen, allerdings gibt es ein paar Platzprobleme (der ATMega in TQFP ist einfach zu klein für die ganzen Bauteile außen herum). Die Firmware wurde nicht verändert und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download des optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] =AVR-Doper unter Windows 7= Nachdem Windows XP schon etwas betagt ist und Vista eher ein flop war, steht man früher oder später an dem Punkt, Windows 7 zu verwenden. Zwar lassen sich die Vista-Treiber des AVR-Dopers unter Windows 7 installieren, AVR-Studio kann allerdings keine Verbindung zum Doper herstellen. Die Jungs von recursion.jp haben einen Treiber geschrieben, der sowohl unter Win7 x86 und Win7 x64 funktioniert: [http://www.recursion.jp/avrcdc/lowbulk.html http://www.recursion.jp/avrcdc/lowbulk.html] -> "avrcdc_inf.zip" Es kann sein, dass der Treiber manuell signiert werden muss (was bei meiner x86-Installation nicht erforderlich war). Nähere Informationen dazu (und auch der ursprüngliche Hinweis auf den Treiber) befinden sich im [http://forums.obdev.at/viewtopic.php?f=8&t=3591&p=12721#p12721 Forum von Objective Development] [[Category:AVR]] [[Category:USB]] [[Category:PC]] 498e7fc14dee64d6aa0c506da8a4fa920c98fbf9 Datei:Nrg zaehler auswert.png 6 178 522 2010-09-01T21:09:08Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg zaehler umlauf.png 6 179 523 2010-09-01T21:09:40Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg zaehler pass.png 6 180 524 2010-09-01T21:29:48Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg zaehler rauschen.png 6 181 525 2010-09-01T21:32:21Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Bananen Frucht.jpg 6 182 526 2010-09-01T21:39:58Z Chris 2 Eine Banane, aus [http://de.wikipedia.org/w/index.php?title=Datei:Bananen_Frucht.jpg&filetimestamp=20060422205009 Wikipedia]. vom Benutzer [http://de.wikipedia.org/wiki/Benutzer:Darkone Darkone] Diese Datei ist unter der Creative Commons-Lizenz [http:// wikitext text/x-wiki Eine Banane, aus [http://de.wikipedia.org/w/index.php?title=Datei:Bananen_Frucht.jpg&filetimestamp=20060422205009 Wikipedia]. vom Benutzer [http://de.wikipedia.org/wiki/Benutzer:Darkone Darkone] Diese Datei ist unter der Creative Commons-Lizenz [http://creativecommons.org/licenses/by-sa/2.5/deed.de Namensnennung-Weitergabe unter gleichen Bedingungen 2.5 US-amerikanisch (nicht portiert)] lizenziert. 4f75243e9e27718955a07c49a2e45382f2fcc7de Datei:Nrg formel leistung.png 6 183 527 2010-09-01T21:47:13Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Nrg json.png 6 184 529 2010-09-01T22:05:29Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 USBLotIO 0 95 531 471 2010-09-29T17:05:12Z Chris 2 Fuses in der Infobox korrigiert wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = 75 | FuseL = E1 | FuseE = FF }} Die parallele Schnittstelle am PC ist tot. Nachdem sie schon vor einigen Jahren bei Notebooks verschwunden ist, findet man sie heute auch kaum noch bei Desktop-PCs. Selbst bei teureren Mainboards sind oft nur noch Pinheader vorhanden. Ein Slotblech dafür wird generell nicht geliefert. Die ganzen Drucker sind jetzt schneller und mit dünneren Leitungen per USB angebunden. Soweit, so gut. Nur wird die Luft für Bastler langsam dünner, wenn man keine größeren Ambitionen zu RS232 hat (deren Anschlüsse am PC auch langsam aussterben). Aus diesem Grund hatte ich die Idee, eine kleine Schaltung zu bauen, die zwar keinen Ersatz aber eine Alternative zum guten alten Parport darstellt. == Anforderungen == * Anbindung, die auch noch in ein paar Jahren funktioniert * Einfacher Aufbau * Einfach vom PC ansprechbar * Erweiterbar == Hardware == [[Bild:Usblotio_sch.png|thumb|Stromlaufplan der Platinen]] Die Anbindung an den PC findet per USB statt. Hier soll (wieder einmal) [http://www.obdev.at/products/vusb/index-de.html V-USB] zum Einsatz kommen. Davon gibt es zwar schon ein Referenzdesign ([http://www.obdev.at/products/vusb/powerswitch.html PowerSwitch]), dieses hat meiner Meinung ein paar Schwachstellen: * keine Erweiterbarkeit * Treiber erforderlich (laufen die vorhandenen überhaupt unter Win7?) * relativ großer Aufbau Diesen Schwächen möchte ich mit einem ATTiny45 entgegenwirken. Dieser ist schön klein und braucht dank PLL (und automatischer Taktkalibrierung per USB) keinen externen Quarz. Damit man keine Treiber braucht, soll er sich dem Computer gegenüber als HID (Human Interface Device) ausgeben. Bleibt nur noch eines: Mit der Anbindung am PC bleiben nur noch 4 Pins am Tiny über - einer davon ist der Reset-Eingang - wie soll man da großartig Ausgänge schalten können? Ganz zu schweigen von der angestrebten Erweiterbarkeit... Die Lösung hierfür ist einfach: der Mikrocontroller steuert Schieberegister an, die beliebig kaskadiert werden können. So kann man quasi beliebig viele Ausgänge an den AVR dengeln. Als Ausgabeschieberegister dienen 74xx595, welche einen Latch haben und die Datenleitungen in einem Rutsch aktualisiert werden können. Um Signale auch lesen zu können, kommen 74xx165 zum Einsatz. Zwar haben diese auch einen Latch, allerdings ist dieser (anders als beim 595) low-aktiv. Damit wird's mit 4 I/Os am AVR eng. Gut, die Strobe-Leitungen muss man trennen, Clock kann gemeinsam laufen, nur sind jetzt schon alle Pins belegt. Es ist zwar möglich, die Daten ins Register zu laden, aber was bringen die Daten, wenn man sie nicht lesen kann? Mit einem kleinen Trick kann man das aber bewältigen: Die Datenleitungen beider Richtungen auf einen I/O. Zum Schutz des Ausganges des Registers gibt es aber einen Reihenwiderstand. Zwischen dem Lesen und Schreiben muss die Datenleitung einfach nur noch als Eingang bzw. Ausgang geschaltet werden. <gallery> Bild:Usblotio_povray.jpg|Mit [http://www.povray.org/ POV-Ray] gerendertes Layout der Platinen Bild:Usblotio_main.jpg|Aufgebaute Hauptplatine des USBLotIO Bild:Usblotio out.jpg|Aufgebautes Ausgabemodul </gallery> Aber Vorsicht: dadurch, dass der Reset-Pin auch verwendet wird, kann der Mikrocontroller nur mit HVSP programmiert werden! (oder man lässt eine "Richtung" weg - noch ungetestet). <b style="color: red;">Ein Wort der Warnung sei noch angebracht:</b> Bei vielen PCs ist die USB-Schnittstelle NICHT abgesichert, bei einem Kurzschluss geht dann die komplette Leistung des Netzteils durch! Das kann zu zerstörten Leiterbahnen (sowohl am USB-Gerät als auch auf dem Mainboard) oder sogar Bränden führen! In der Firmware ist eine Stromaufnahme von 20mA angegeben, welche schon bei kleineren Aufbauten überschritten werden kann. Die Inbetriebnahme findet unter eigener Verantwortung statt! Rechnungen für neue Mainboards o.a. an mich werden mit Freude durch den Aktenvernichter gejagt. == Software == === AVR === Wie bereits erwähnt läuft auf dem AVR objective developments V-USB als HID. Grundlage für meine Implementierung war das "Datastore"-Beispiel, das zusätzlich um die automatische Kalibrierung der CPU-Frequenz erweitert wurde. Da die USB-Schnittstelle zwangsläufig auf einem Interrupt-Pin hängt, der gleichzeitig auch für SPI verantwortlich ist, müssen die Schieberegister mit einem wesentlich langsameren Soft-SPI angesprochen werden. Der USB-Client reagiert bei dem Beginn einer Übertragung mit einem Aufruf der Methode usbFunctionSetup. In ihr wird dann entschieden, ob es sich um einen Schreib- oder Lesevorgang handelt. Hier wird zum einen die Speicheradresse auf 0 gesetzt und beim Leseaufruf die Zustände der Registereingänge in den RAM geschrieben. Anschließend wird von V-USB usbFunctionWrite bzw. usbFunctionRead je nach Reportgröße mehrmals aufgerufen. Im Read wird einfach nur der Inhalt des RAMs an den PC übertragen, beim Schreiben wird zuerst die Variable (die gleiche wie beim Lesen) gefüllt und nach dem letzten Wert vom PC die Methode processCommand aufgerufen. Die übertragenen Werte werden in Anschlussreihenfolge aus Sicht der Hauptplatine angegeben. Gibt man z.B. 0x01 0x02 aus, wird am Ausgabemodul, das am nächsten zur Hauptplatine angeschlossen ist 0x01 ausgegeben, am "zweitnächsten" 0x02. Bei den Eingabemodulen verhält es sich genauso. Dort findet das eigentliche Schreiben auf die Register statt. Zusätzlich zum simplen Schreiben kann man den Controller mit ein paar Logikfunktionen beauftragen. Diese werden immer mit der letzten Ausgabe verarbeitet. Folgende Operationen sind möglich: * Überschreiben * OR * AND * XOR Zusätzlich kann man ein Flag zum Invertieren übergeben, dadurch werden die Funktionen NOR, NAND und XNOR sowie invertiertes Überschreiben ermöglicht. Mit einem weiteren Flag kann man die errechneten Werte ins EEProm des Controllers schreiben. Dadurch kann man direkt beim Einschalten der Hardware einen definierten Zustand ausgeben. Das einzige, das man in der Software noch anpassen muss, ist die Anzahl der jeweiligen Schieberegister. Oder einfach unverändert lassen - dann werden jeweils 8 Register angenommen. Diese Werte muss man nur anpassen, wenn man mehr als 8 Schieberegister verwendet oder mehr Performance (Auswirkung noch nicht geprüft) wünscht. Ferner kann man eine ID in den EEProm schreiben, um mehrere (256) Devices zu unterscheiden. Diese ID wird bei jedem Lese-Vorgang im untersten Byte des Reports zurückgegeben. [[Bild:Usblotio_fuses.png|thumb|Im AVR programmierte Fuses]] Damit man die Hardware vollständig genutzt werden kann, müssen die Fuses wie folgt programmiert werden (siehe auch Screenshot oder in der Infobox oben): * Extended: 0xFF * High: 0x75 * Low: 0xE1 SPIEN kann nur deaktiviert werden, wenn man per HVSP programmiert, RSTDISBL ''sollte'' eigentlich reichen, habe ich allerdings nicht ausprobiert ;-) === PC === Auf dem PC kann eigentlich alles werkeln, was auf die entsprechenden USB-APIs zugreifen kann. Ich beschränke mich auf Windows, die Portierung auf *nix/Mac/etc. sollte aber nicht allzu schwierig sein. Im Grunde muss man nicht viel machen, das Schwierigste dürfte wahrscheinlich das Finden des Devices sein. Ich habe im C#-Programm Teile aus der [http://www.brianpeek.com/blog/pages/wiimotelib.aspx WiimoteLib] von Brian Peek genommen. Ist das HID gefunden und ein Handler gesetzt, können mit HidD_SetFeature und -GetFeature Reports an den AVR gesendet oder von ihm angefordert werden. Wichtig ist hier eigentlich nur die Größe des übergebenen Arrays, bei falscher Länge kommt oft einfach nichts beim Device an! Man kann relativ viel Zeit damit verbringen, dort nach einem Fehler zu suchen, zumal sich ein vollbelegter Mikrocontroller (dessen UART man nicht verwenden kann) schlecht debuggen lässt. Zur Demonstration habe ich eine kleine Konsolen-Anwendung rund um die USBLotIO-Klasse geschrieben. Kann sein, dass ich die Klasse noch ein wenig umstrukturiere - die nullable Byte-Arrays gefallen mir nicht sonderlich. Im Ordner \csharp\USBlotIO\bin\Release\ befindet sich ein kleines Konsolenprogramm (USBlotIO.exe), mit dem man alle Features der Hardware testen/nutzen kann. Einfach einmal ohne Parameter starten, dann werden alle möglichen Aufrufe angezeigt (wem es beim Start per Doppelklick zu schnell geht: cmd starten und damit die Anwendung aufrufen). == Test == Die Hardwareinstallation ist im Baukastenprinzip. Module anstecken und per USB-Kabel mit dem PC verbinden. Nach wenigen Sekunden ist das Gerät bereit für die Verwendung. Leider konnte ich das Board für Eingabemodule nicht testen, da Reichelt keine 74xx165 in SMD hat. Auf dem Breadboard hat es funktioniert, dennoch gebe ich momentan keine 100%ige Garantie auf korrekte Funktion! Erfolgreich getestet wurde die C#-Anwendung bisher unter WinXP Pro SP3 sowie Windows 7. Für Vista brauche ich erst noch einen Probanden, Windows 2000 lasse ich außen vor (freue mich aber über Erfolgsmeldungen). == Download == [[Datei:Usblotio.zip]] Firmware, EAGLE-Dateien und C#-Testprogramm (VS2008, .NET 2.0) [[Category:AVR]] [[Category:USB]] [[Category:PC]] 022ea108f6e19dfefb55776469af03df32733509 VBus-Decoder 0 120 532 472 2010-09-30T18:53:12Z Chris 2 Info zum verwendeten Transistor für die Rückleitung wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die zwar Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <pre> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </pre> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <pre> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </pre> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Maschinen]] 0a192a4fccccfd8fe7fa24347ef2e9e74f292bfe Datei:Canon Klinke.png 6 185 533 2010-10-10T20:46:31Z Chris 2 Original von: http://de.wikipedia.org/w/index.php?title=Datei:3mm5_jack_3_norm.svg&filetimestamp=20080613173526 Benedikt.Seidl Own work, copyleft: Multi-license with GFDL and Creative Commons CC-BY-SA-2.5 and older versions (2.0 and 1.0) wikitext text/x-wiki Original von: http://de.wikipedia.org/w/index.php?title=Datei:3mm5_jack_3_norm.svg&filetimestamp=20080613173526 Benedikt.Seidl Own work, copyleft: Multi-license with GFDL and Creative Commons CC-BY-SA-2.5 and older versions (2.0 and 1.0) aca5369cb34a2d84abcf8b4c3abc684f11c6611f Datei:Kameratimer sch.png 6 186 534 2010-10-10T20:47:17Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Kameratimer brd.png 6 187 535 2010-10-10T20:47:31Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Kameratimer stecker.JPG 6 188 536 2010-10-10T20:48:04Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Kameratimer schnuller.JPG 6 189 537 2010-10-10T20:48:32Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Kameratimer.JPG 6 190 538 2010-10-10T20:49:27Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Kameratimer gehaeusse.jpg 6 191 539 2010-10-10T20:50:05Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Kameratimer 0 192 540 2010-10-10T21:05:26Z Chris 2 Seite erstellt wikitext text/x-wiki [[Datei:Kameratimer.JPG|thumb|Der fertige Timer samt Kamera]] [[Datei:Kameratimer gehaeusse.jpg|thumb|Gehäuse des Timers - das mit den Ausschnitten übe ich noch...]] Nachdem sich meine alte Kompaktkamera kurzzeitig [http://hobbyelektronik.org/b/?p=132 verabschiedet] hat und ich für den Urlaub etwas kleineres wollte, legte ich mir einen Ersatz zu. Ergebnis: Es liegen 3 funktionierende Digitalkameras herum. Um die wieder gut funktionierende PowerShot nicht in der Ecke vergammeln zu lassen und mich schon länger Zeitraffer-Aufnahmen interessieren, beschloss ich, das Teil ein wenig umzubauen: = Fernauslöser für die PowerShot A95 = Das Fernauslösen der A95 ist zwar möglich, jedoch nur per PC und einer Software von Canon. Mit ihr können zwar auch Zeitraffer-Aufnahmen gemacht werden, allerdings ist es nicht besonders effizient und auch umständlich, den Computer zu transportieren bzw. tagelang laufen zu lassen. Eine weitere Möglichkeit der Fernauslösung existiert nicht, da weder Auslöser-Eingang noch eine modifizierte Firmware bzw. Erweiterung wie [http://chdk.wikia.com/wiki/CHDK CHDK] für die Kamera existiert. Also muss man selber für den Fernauslöser-Eingang sorgen. Die Peripherie rund um die Hauptplatine ist hauptsächlich in Flexprint (dieses Polyimid-Zeug) ausgeführt, das man nicht gerade mit einem Dachrinnenbrater bearbeiten sollte. Gleichzeitg sind die Leiterbahnen sehr fein und lassen sich manuell schlecht verfolgen. Hier hilft es, die verdächtigen Stellen zu fotografieren und die Leiterbahnen mit Bildbearbeitung zu markieren und verfolgen. Praktischerweise enden die für den Auslöser relevanten Leitungen an einer gut erreichbaren Stelle und sind gut lötbar. Mit Fädeldraht kontaktiert muss das Zeug nur noch von außen erreichbar werden. Zum Glück findet sich im Gehäuse noch ein freies Fleckchen: neben dem Stromanschluss ist genug Platz für eine Buchsenleiste im 1,27mm Rastermaß. Für diese muss lediglich die Gummiabdeckung der restlichen Buchsen weichen. Mit Epoxid-Kleber hält das Teil bombenfest und die Kamera sieht von außen fast normal aus. Leider existieren von der internen Verdrahtung keine detaillierten Fotos. Bei Interesse kann ich diese jedoch gerne nachreichen. = Auslöser = {{Infobox AVR | Typ = ATtiny26 | Takt = 3,2768 | FuseH = F4 | FuseL = B7 }} Jetzt muss die Kamera "nur noch" ausgelöst werden. Schließlich wäre das Ziel verfehlt, wenn man den ganzen Tag mit Uhr neben der Knipse sitzen und aufs Knöpfchen drücken müsste. Diesen Job soll ein ATTiny26 übernehmen, dessen Speicher sich im Nachhinein als etwas knapp erwiesen hat. Um den AVR versammeln sich nur wenige Komponenten: Als Taktquelle dient ein 3,2768MHz Quarz, die Anzeige übernimmt ein 1x20 Character LCD und zur Eingabe dient ein Drehgeber mit Taster den ich mal aus einer HP-Knipse geschlachtet habe. Zum Auslösen selbst wird ein einfacher Optokoppler (Typ weitestgehend unbekannt) verwendet. Der Drehgeber hat einen Vorteil und gleichzeitig auch Nachteil: Eine Raste sind zwei Übergänge der Ausgänge. Dadurch wird die Software nicht kompatibel mit anderen Drehgebern. Vorteil: die Auswertung ist etwas kompakter. Das LCD wird (nach Anfangsschwierigkeiten mit einer anderen Bibliothek) mit dem großartigen Code von [http://www.jump.to/fleury Peter Fleury] angesteuert. == Bedienkonzept == Ohne gute Bedienbarkeit hilft der beste Code im Hintergrund nichts. Zugegebenermaßen muss man sich bei einer etwas besseren Eieruhr keine Gedanken über die Usability machen, ein klein bisschen Komfort sollte aber drin sein. Die Software kennt vier Menüpunkte: * Low-Zeit des Ausgangs (L) * High-Zeit des Ausgangs (H) * Anzahl der Schaltvorgänge (n) * Statusanzeige/Verbleibende Zeit zum Zustandswechsel (R) Die Dauer der High-Zeit ist für Langzeitbelichtungen im BULB-Modus (also deutlich über den maximalen 30 Sekunden – nur für Spiegelreflexen relevant) gedacht. Mit dem Drehgeber kann man im ersten Modus durch die verschiedenen Menüpunkte wechseln. Drückt man den Drehgeber, wechselt der Modus zur Stellenwahl. Hier kann man nun auswählen, welche Stelle des angezeigten Werts bearbeiten will. Nach einem weiteren Druck kann man dann durch Drehen den Wert erhöhen bzw. verringern. Die verschiedenen Modi rotieren momentan durch. Intuitiver wäre es meiner Meinung noch, wenn man zwischen Wahl der Stelle und Erhöhen/Verringern so lange hin und her wechselt, bis man nicht mehr "am Rädchen dreht". Damit man auch weiß was man macht, wir der aktuelle Modus per Symbol auf dem Display angezeigt. Neben dem Modussymbol wird angezeigt, ob der Timer aktuell läuft (Play-/Stopp-Symbol), da die Parameter auch während dem Laufen des Timers verändert werden können. Bei der Anzeige der verbleibenden Zeit zum Zustandswechsel wird zusätzlich die nächste Flanke (steigend oder fallend) angezeigt. == Software == Herzstück ist der Timer des AVRs, der eine Zeitbasis von 0.1 Sekunden schafft. Dies ist gleichzeitig auch die kleinste einstellbare Einheit. Im Timer-Interrupt wird die komplette Verarbeitung der Schaltzeiten und der Ausgabe übernommen. Das Benutzerinterfache ist komplett im (berüchtigten) Main-Loop untergebracht. Sämtliche Benutzereingaben werden gepollt. Um das Entprellen der Taster zu sparen ist der restliche Code bewusst *hust* ineffizient. == Aufbau == Ursprünglich sollte die Schaltung (aufgrund der geringen Komplexität) auf Lochraster aufgebaut werden. Nachdem ich sowieso ein paar Leiterplatten fertigen lassen wollte, kam das Layout eben noch dazu. <gallery> Bild:Kameratimer_sch.png|Stromlaufplan Bild:Kameratimer_brd.png|Board </gallery> Das verwendete Display hat seine Anschlüsse mit 2x7 Pins auf der linken Seite. Dementsprechend wurde die Anschlussbelegung am Mikrocontroller angepasst. Mit Stift- und Buchsenleiste ist der Abstand zwischen Platine und Display genau so, dass man die ICs sockeln kann. Leider passt der hohe Quarz nicht mehr stehend darunter (zumindest der, den ich da hatte). An zwei Stellen war noch etwas knobeln angesagt: Beim Anschluss der Kamera und des Drehgebers. Leider hatte ich mir beim Test auf dem Breadboard nicht aufgeschrieben, wo was war. Etwas hakelig war auch die Kontrastspannung – aus irgendwelchen Gründen habe ich auch nach längerem probieren keine vernünftige Widerstandskombination gefunden. Schlussendlich habe ich am Rand der Platine ein Poti angelötet. == Anschluss an die Kamera == [[Datei:Canon Klinke.png|thumb|Belegung des 2.5mm-Klinkensteckers für Canon-Fernauslöser]] Der Anschluss für die Kamera ist eine 2,5mm-Klinkenbuchse. Diese hat den Vorteil, dass man die kleineren Spiegelreflexen von Canon direkt mit einem einfachen Klinkenverbinder angeschlossen werden können. Am Fernauslösereingang der SLRs (zumindest an der EOS 400D) liegt eine Spannung von 3,3V an, beim Ziehen auf Masse wird je nach Pin entweder fokussiert oder ausgelöst. Zieht man den Pin zum Auslösen auf Masse, ohne zuvor zu fokussieren (oder auf manuellen Fokus eingestellt zu haben), holt dies die Kamera vor dem Auslösen nach, was den Vorgang verzögert. Dieses Verhalten habe ich bei der PowerShot nicht beobachten können. Wird nur die Leitung zum Auslösen auf Masse gezogen, passiert nichts. Werden beide Leitungen gleichzeitig auf Masse gezogen, löst die Kamera ohne Probleme aus. Um einen zusätzlichen Optokoppler zu sparen, habe ich die Fokussier- und Auslöseleitung im Timer verbunden. Das hat zur Folge, dass die Kamera, wenn sie am Timer angeschlossen ist, auch dann auslöst, wenn man den Auslöser nur halb drückt. Die Verschaltung scheint nach einem Blick auf die Innereien des [http://www.eosdoc.com/manuals/?q=RS-60E3 RS-60E3] üblich zu sein und sollte zu keinen Problemen führen. = Trivia = Die Software/Hardware hat mich ziemlich gefuchst. Aufgrund des Platzmangels war kein Debugging über UART möglich, Hardware für „richtiges“ Debugging ist leider auch nicht vorhanden. Ich habe bis heute nicht herausgefunden, woran sich der AVR gestört hat. Manchmal funktionierte das Teil, manchmal auch nach dem 10. Mal einschalten noch nicht. Auch ein nachträglicher Reset brachte nichts – es war wie verhext. Es war kein offensichtlicher Hard- oder Softwarefehler zu finden. Eines ist sicher: Nie wieder Smileys auf einem Layout. Die Probleme waren auch der Grund dafür, warum ich das Projektchen erst fast ein Jahr nach dem eigentlichen Aufbau dokumentiere. = Tipps für Aufnahmen = Beim ersten Test musste eine Amaryllis herhalten. Aus dem Versuch kommen folgende Erkenntnisse: * Energiesparlampen sind trotz Weißabgleich für die Beleuchtung ungeeignet * Bildausschnitt immer großzügig wählen, zuschneiden kann man später immer noch * Manuellen Fokus verwenden ** Geringere Auslöseverzögerung ** Vermeidung wandern der Schärfeebene ** Schärfenebene so einstellen, damit zum Schluss auch das Interessante scharf ist * Bei der Aufnahmedauer, dem Intervall und dem damit verbundenen Speicherplatzbedarf lieber zweimal rechnen * Bildnummerierung vor der Aufnahme zurücksetzen [[Datei:Kameratimer_schnuller.JPG|thumb|"Stromspar"-Stecker]] Leider löschen die ganzen kompakten Canons den AF-Lock, sobald das Display abgeschaltet wird. Mit einem kleinen Trick kann man das Display abschalten, ohne die Aufnahmeparameter zu beeinflussen: Steckt man eine 3,5mm-Klinke in den Videoausgang, wird das interne Display abgeschaltet. Der Bildsensor bleibt bei diesem „Trick“ jedoch aktiv, was eine deutlich höhere Stromaufnahme im Gegensatz zum Standby-Modus bedeutet. Bei einer zweiten Testaufnahme eines Sonnenuntergangs habe ich festgestellt, dass die automatische Belichtungssteuerung erstaunlich „geschmeidig“ arbeitet. Unter den knapp 400 Fotos waren trotz kurzzeitigem Gegenlicht keine Ausreißer. Als Warnung sei noch angebracht, dass Bildsensoren nicht unbedingt dafür ausgelegt sind, längerer Zeit direkte Sonneneinstrahlung auszuhalten. Auf gut Deutsch: Wenn man einen Zeitraffer von der Sonne macht, kann mit dem Bildsensor dasselbe wie Ameisen passieren, die mit der Lupe brutzelt. = Download = kommt noch ;) 71aa927fd3ae6325bf27a378c0b606410012b21d 546 540 2010-10-11T19:23:24Z Chris 2 /* Download */ wikitext text/x-wiki [[Datei:Kameratimer.JPG|thumb|Der fertige Timer samt Kamera]] [[Datei:Kameratimer gehaeusse.jpg|thumb|Gehäuse des Timers - das mit den Ausschnitten übe ich noch...]] Nachdem sich meine alte Kompaktkamera kurzzeitig [http://hobbyelektronik.org/b/?p=132 verabschiedet] hat und ich für den Urlaub etwas kleineres wollte, legte ich mir einen Ersatz zu. Ergebnis: Es liegen 3 funktionierende Digitalkameras herum. Um die wieder gut funktionierende PowerShot nicht in der Ecke vergammeln zu lassen und mich schon länger Zeitraffer-Aufnahmen interessieren, beschloss ich, das Teil ein wenig umzubauen: = Fernauslöser für die PowerShot A95 = Das Fernauslösen der A95 ist zwar möglich, jedoch nur per PC und einer Software von Canon. Mit ihr können zwar auch Zeitraffer-Aufnahmen gemacht werden, allerdings ist es nicht besonders effizient und auch umständlich, den Computer zu transportieren bzw. tagelang laufen zu lassen. Eine weitere Möglichkeit der Fernauslösung existiert nicht, da weder Auslöser-Eingang noch eine modifizierte Firmware bzw. Erweiterung wie [http://chdk.wikia.com/wiki/CHDK CHDK] für die Kamera existiert. Also muss man selber für den Fernauslöser-Eingang sorgen. Die Peripherie rund um die Hauptplatine ist hauptsächlich in Flexprint (dieses Polyimid-Zeug) ausgeführt, das man nicht gerade mit einem Dachrinnenbrater bearbeiten sollte. Gleichzeitg sind die Leiterbahnen sehr fein und lassen sich manuell schlecht verfolgen. Hier hilft es, die verdächtigen Stellen zu fotografieren und die Leiterbahnen mit Bildbearbeitung zu markieren und verfolgen. Praktischerweise enden die für den Auslöser relevanten Leitungen an einer gut erreichbaren Stelle und sind gut lötbar. Mit Fädeldraht kontaktiert muss das Zeug nur noch von außen erreichbar werden. Zum Glück findet sich im Gehäuse noch ein freies Fleckchen: neben dem Stromanschluss ist genug Platz für eine Buchsenleiste im 1,27mm Rastermaß. Für diese muss lediglich die Gummiabdeckung der restlichen Buchsen weichen. Mit Epoxid-Kleber hält das Teil bombenfest und die Kamera sieht von außen fast normal aus. Leider existieren von der internen Verdrahtung keine detaillierten Fotos. Bei Interesse kann ich diese jedoch gerne nachreichen. = Auslöser = {{Infobox AVR | Typ = ATtiny26 | Takt = 3,2768 | FuseH = F4 | FuseL = B7 }} Jetzt muss die Kamera "nur noch" ausgelöst werden. Schließlich wäre das Ziel verfehlt, wenn man den ganzen Tag mit Uhr neben der Knipse sitzen und aufs Knöpfchen drücken müsste. Diesen Job soll ein ATTiny26 übernehmen, dessen Speicher sich im Nachhinein als etwas knapp erwiesen hat. Um den AVR versammeln sich nur wenige Komponenten: Als Taktquelle dient ein 3,2768MHz Quarz, die Anzeige übernimmt ein 1x20 Character LCD und zur Eingabe dient ein Drehgeber mit Taster den ich mal aus einer HP-Knipse geschlachtet habe. Zum Auslösen selbst wird ein einfacher Optokoppler (Typ weitestgehend unbekannt) verwendet. Der Drehgeber hat einen Vorteil und gleichzeitig auch Nachteil: Eine Raste sind zwei Übergänge der Ausgänge. Dadurch wird die Software nicht kompatibel mit anderen Drehgebern. Vorteil: die Auswertung ist etwas kompakter. Das LCD wird (nach Anfangsschwierigkeiten mit einer anderen Bibliothek) mit dem großartigen Code von [http://www.jump.to/fleury Peter Fleury] angesteuert. == Bedienkonzept == Ohne gute Bedienbarkeit hilft der beste Code im Hintergrund nichts. Zugegebenermaßen muss man sich bei einer etwas besseren Eieruhr keine Gedanken über die Usability machen, ein klein bisschen Komfort sollte aber drin sein. Die Software kennt vier Menüpunkte: * Low-Zeit des Ausgangs (L) * High-Zeit des Ausgangs (H) * Anzahl der Schaltvorgänge (n) * Statusanzeige/Verbleibende Zeit zum Zustandswechsel (R) Die Dauer der High-Zeit ist für Langzeitbelichtungen im BULB-Modus (also deutlich über den maximalen 30 Sekunden – nur für Spiegelreflexen relevant) gedacht. Mit dem Drehgeber kann man im ersten Modus durch die verschiedenen Menüpunkte wechseln. Drückt man den Drehgeber, wechselt der Modus zur Stellenwahl. Hier kann man nun auswählen, welche Stelle des angezeigten Werts bearbeiten will. Nach einem weiteren Druck kann man dann durch Drehen den Wert erhöhen bzw. verringern. Die verschiedenen Modi rotieren momentan durch. Intuitiver wäre es meiner Meinung noch, wenn man zwischen Wahl der Stelle und Erhöhen/Verringern so lange hin und her wechselt, bis man nicht mehr "am Rädchen dreht". Damit man auch weiß was man macht, wir der aktuelle Modus per Symbol auf dem Display angezeigt. Neben dem Modussymbol wird angezeigt, ob der Timer aktuell läuft (Play-/Stopp-Symbol), da die Parameter auch während dem Laufen des Timers verändert werden können. Bei der Anzeige der verbleibenden Zeit zum Zustandswechsel wird zusätzlich die nächste Flanke (steigend oder fallend) angezeigt. == Software == Herzstück ist der Timer des AVRs, der eine Zeitbasis von 0.1 Sekunden schafft. Dies ist gleichzeitig auch die kleinste einstellbare Einheit. Im Timer-Interrupt wird die komplette Verarbeitung der Schaltzeiten und der Ausgabe übernommen. Das Benutzerinterfache ist komplett im (berüchtigten) Main-Loop untergebracht. Sämtliche Benutzereingaben werden gepollt. Um das Entprellen der Taster zu sparen ist der restliche Code bewusst *hust* ineffizient. == Aufbau == Ursprünglich sollte die Schaltung (aufgrund der geringen Komplexität) auf Lochraster aufgebaut werden. Nachdem ich sowieso ein paar Leiterplatten fertigen lassen wollte, kam das Layout eben noch dazu. <gallery> Bild:Kameratimer_sch.png|Stromlaufplan Bild:Kameratimer_brd.png|Board </gallery> Das verwendete Display hat seine Anschlüsse mit 2x7 Pins auf der linken Seite. Dementsprechend wurde die Anschlussbelegung am Mikrocontroller angepasst. Mit Stift- und Buchsenleiste ist der Abstand zwischen Platine und Display genau so, dass man die ICs sockeln kann. Leider passt der hohe Quarz nicht mehr stehend darunter (zumindest der, den ich da hatte). An zwei Stellen war noch etwas knobeln angesagt: Beim Anschluss der Kamera und des Drehgebers. Leider hatte ich mir beim Test auf dem Breadboard nicht aufgeschrieben, wo was war. Etwas hakelig war auch die Kontrastspannung – aus irgendwelchen Gründen habe ich auch nach längerem probieren keine vernünftige Widerstandskombination gefunden. Schlussendlich habe ich am Rand der Platine ein Poti angelötet. == Anschluss an die Kamera == [[Datei:Canon Klinke.png|thumb|Belegung des 2.5mm-Klinkensteckers für Canon-Fernauslöser]] Der Anschluss für die Kamera ist eine 2,5mm-Klinkenbuchse. Diese hat den Vorteil, dass man die kleineren Spiegelreflexen von Canon direkt mit einem einfachen Klinkenverbinder angeschlossen werden können. Am Fernauslösereingang der SLRs (zumindest an der EOS 400D) liegt eine Spannung von 3,3V an, beim Ziehen auf Masse wird je nach Pin entweder fokussiert oder ausgelöst. Zieht man den Pin zum Auslösen auf Masse, ohne zuvor zu fokussieren (oder auf manuellen Fokus eingestellt zu haben), holt dies die Kamera vor dem Auslösen nach, was den Vorgang verzögert. Dieses Verhalten habe ich bei der PowerShot nicht beobachten können. Wird nur die Leitung zum Auslösen auf Masse gezogen, passiert nichts. Werden beide Leitungen gleichzeitig auf Masse gezogen, löst die Kamera ohne Probleme aus. Um einen zusätzlichen Optokoppler zu sparen, habe ich die Fokussier- und Auslöseleitung im Timer verbunden. Das hat zur Folge, dass die Kamera, wenn sie am Timer angeschlossen ist, auch dann auslöst, wenn man den Auslöser nur halb drückt. Die Verschaltung scheint nach einem Blick auf die Innereien des [http://www.eosdoc.com/manuals/?q=RS-60E3 RS-60E3] üblich zu sein und sollte zu keinen Problemen führen. = Trivia = Die Software/Hardware hat mich ziemlich gefuchst. Aufgrund des Platzmangels war kein Debugging über UART möglich, Hardware für „richtiges“ Debugging ist leider auch nicht vorhanden. Ich habe bis heute nicht herausgefunden, woran sich der AVR gestört hat. Manchmal funktionierte das Teil, manchmal auch nach dem 10. Mal einschalten noch nicht. Auch ein nachträglicher Reset brachte nichts – es war wie verhext. Es war kein offensichtlicher Hard- oder Softwarefehler zu finden. Eines ist sicher: Nie wieder Smileys auf einem Layout. Die Probleme waren auch der Grund dafür, warum ich das Projektchen erst fast ein Jahr nach dem eigentlichen Aufbau dokumentiere. = Tipps für Aufnahmen = Beim ersten Test musste eine Amaryllis herhalten. Aus dem Versuch kommen folgende Erkenntnisse: * Energiesparlampen sind trotz Weißabgleich für die Beleuchtung ungeeignet * Bildausschnitt immer großzügig wählen, zuschneiden kann man später immer noch * Manuellen Fokus verwenden ** Geringere Auslöseverzögerung ** Vermeidung wandern der Schärfeebene ** Schärfenebene so einstellen, damit zum Schluss auch das Interessante scharf ist * Bei der Aufnahmedauer, dem Intervall und dem damit verbundenen Speicherplatzbedarf lieber zweimal rechnen * Bildnummerierung vor der Aufnahme zurücksetzen [[Datei:Kameratimer_schnuller.JPG|thumb|"Stromspar"-Stecker]] Leider löschen die ganzen kompakten Canons den AF-Lock, sobald das Display abgeschaltet wird. Mit einem kleinen Trick kann man das Display abschalten, ohne die Aufnahmeparameter zu beeinflussen: Steckt man eine 3,5mm-Klinke in den Videoausgang, wird das interne Display abgeschaltet. Der Bildsensor bleibt bei diesem „Trick“ jedoch aktiv, was eine deutlich höhere Stromaufnahme im Gegensatz zum Standby-Modus bedeutet. Bei einer zweiten Testaufnahme eines Sonnenuntergangs habe ich festgestellt, dass die automatische Belichtungssteuerung erstaunlich „geschmeidig“ arbeitet. Unter den knapp 400 Fotos waren trotz kurzzeitigem Gegenlicht keine Ausreißer. Als Warnung sei noch angebracht, dass Bildsensoren nicht unbedingt dafür ausgelegt sind, längerer Zeit direkte Sonneneinstrahlung auszuhalten. Auf gut Deutsch: Wenn man einen Zeitraffer von der Sonne macht, kann mit dem Bildsensor dasselbe wie Ameisen passieren, die mit der Lupe brutzelt. = Download = [[Datei:Kameratimer.zip]] 5ed31bcd98e6127df9050a823f6c6e4c395835d7 Datei:Kameratimer.zip 6 193 545 2010-10-11T19:22:25Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Image Resizer 0 63 547 418 2010-10-18T13:10:52Z Chris 2 /* Download */ wikitext text/x-wiki ==Ausgangssituation== Eine Bekannte mit mäßigen Kenntnissen in Bildbearbeitung möchte in regelmäßigen Zeitabständen Bilder auf ihre Homepage hochladen. ==Problem== Die Bilder von der Digitalkamera sind groß und die Internetverbindung langsam. Also müssen sie in zwei Hinsichten verkleinert werden: Bildgröße und Dateigröße. ==Lösung== PHP war schon öfter der schnelle (und v.a. dreckige) Weg zum Erfolg. Also habe ich Teile meines schon etwas in die Tage gekommenen [http://hobbyelektronik.org/fotos Foto-Albums] verwertet und ein kleines Script erstellt, das die Arbeit übernimmt. Damit die gute Frau die Bilder nicht auf meinen Webserver hochladen muss um sie dann kleiner wieder zu bekommen (hirnrissig, siehe Problem), soll das ganze auf dem eigenen PC laufen - ohne Webserver. PHP bietet von sich aus ein CLI (Commandline-Interface) an, dafür braucht man allerdings trotzdem alle PHP-bezogenen Dateien. Ungut, weil man etwas falsch machen kann... Dank Bambalam und seinem Compiler/Embedder [http://www.bambalam.se/bamcompile/ Bamcompile] kann man aus PHP-Scripts selbstständig lauffähige EXE-Dateien erstellen - sogar mit Extensions! Also habe ich das Script etwas mehr auf CLI angepasst und mit Bamcompile zur Executable verarbeitet. ==Verwendung== Einfach Bilddateien (JPG, GIF, PNG) auf resize.exe ziehen und schon wird verkleinert. Die verkleinerten Bilder werden im gleichen Ordner erstellt und ihnen wird ein "_sm" angehängt, aus IMG_1234.JPG wird also IMG_1234_sm.JPG Achtung: bestehende Dateien mit diesem Namen werden ohne Rückfrage überschrieben Momentan wird die lange Kante des Bildes auf 1600 Pixel verkleinert, das Seitenverhältnis bleibt gleich. Bei JPEG wird standardmäßig eine Qualitätsstufe von 90% verwendet. Beide Werte können in der resize.php ganz oben verändert werden, danach muss sie aber neu kompiliert werden. Ich habe einige Testbilder (ok, 10 Megapixel) um sage und schreibe 90% komprimieren können. ==Download== [[Datei:Resizepics.zip]] (350 KB) Nach dem Download muss nur noch die ZIP dekomprimiert werden und einmal compile.bat ausgeführt werden (die EXE liegt aus Platzgründen nicht dabei, <strike>dafür der Compiler</strike>) Den Compiler habe ich auf Wunsch meines Hosters gelöscht, da er anscheinend ähnliche Strukturen wie ein Virus hat. Der Compiler selbst kann unter [http://www.bambalam.se/bamcompile/] heruntergeladen werden. Benutzung selbstverständlich auf eigene Gefahr. [[Category:Software]] 7a96f0166b910a392160d3db50b1c58ed539c2c2 Datei:Energieerfassung Firmware.zip 6 194 548 2010-11-15T19:42:08Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Energieerfassung 0 168 549 543 2010-11-15T19:45:04Z Chris 2 /* Downloads */ wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== [[Datei:Nrg hauptzaehler.jpg|thumb|Stromzähler mit aufgesetzter Erfassungseinheit]] Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[:wpde:Ferraris-Zähler|Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. [[Datei:Bananen Frucht.jpg|thumb|Eine Banane, eisenreich und sehr bekömmlich (cc:by-sa Darkone)]] Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. <gallery> Datei:Nrg zaehler umlauf.png|Ein Umlauf, wie er direkt am Fototransistor gemessen wird Datei:Nrg zaehler rauschen.png|"Grundrauschen" der rotierenden Scheibe (ohne DC-Offset) </gallery> Die Leistungsaufnahme lässt sich anhand der Umlaufzeit wie folgt berechnen: [[Datei:Nrg formel leistung.png]] Setzt man die im Screenshot ermittelten 42.6 Sekunden ein, erhält man eine Leistung von ~1127 Watt. Da die Leistung mit der Zeit exponentiell abnimmt, ist bei hohen Leistungsaufnahmen eine relativ hohe Auflösung der Zeit erforderlich. Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: <gallery> Datei:Nrg zaehler auswert.png|Auswerteschaltung Datei:Nrg zaehler pass.png|Zählersignal vor (blau) und nach (gelb) dem Filter </gallery> Links wird der Fototransistor in Sperrrichtung angeschlossen. Der 1µF-Elko und der nachfolgende 100k-Widerstand stellt einen Hochpass mit nicht näher definierter Grenzfrequenz (WolframAlpha sagt [http://www.wolframalpha.com/input/?i=1%2F%282*Pi*100kOhms*1%C2%B5F%29 1.592Hz]) dar. Die Frequenz ist ist im Hinblick auf [[:wpde:Hochpass:Ordnung]], Bauteiletoleranzen und der Zielfrequenz vermutlich nicht einmal ein Richtwert. Der folgende Hochpass hat eine Grenzfrequenz von ca. 16Hz. Hier gilt das gleiche Vertrauen wie in den Tiefpass. Aber alles kein Problem: Die Werte sind weitestgehend unkritisch. Es sind Umläufe im Millihertz-Bereich (also Umlaufdauern in der Größenordnung Sekunden bis Minuten) zu erwarten. Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. [[Datei:Nrg tarifzaehler.jpg|thumb|Tarifzähler, rechts das Fähnchen zum Anzeigen des Tarifs]] Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. [[Datei:Nrg_relais_freigabe.jpg|thumb|Relais für die Stromfreigabe, mit LED]] Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. '''Update 10.10.2010:''' Weasel (IRC) ist beim Anblick der Kennlinie der Temperatursensoren in der Anleitung des Vitosolic 200 blitzschnell darauf gekommen, dass es sich um PT500-Elemente handeln müssen, die jedoch nur für sehr teuer Geld erhältlich sind. Mein anfänglicher Scherz vonwegen 2 PT1000 parallel ergibt PT500 hat sich als gar nicht so dumm erwiesen: Idealerweise sind die Widerstände der Sensoren bei gleicher Temperatur ebenfalls gleich, Durch Parallelschaltung zweier PT1000 kann man sie problemlos an der PT1000 betreiben! Da ich sonst nichts mit meinen 9 Sensoren anzufangen wusste, fristen jetzt 8 dieser als 4 Fühler im Keller ihr dasein: Zwei erfassen die Ein- und Auslasstemperatur an der "Primärseite" der Wärmepumpe, einer sitzt im Warmwasserspeicher in oberster Schicht und der 4. misst (da mir noch nichts besseres einfiel) die Raumtemperatur im Heizkeller, die mangels Isolierung der Rohre deutlich zu hoch ist. ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. <gallery> Datei:Nrg shield.jpg|Shield des Großhirns Datei:Nrg grosshirn.jpg|Hirn von oben </gallery> ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. <gallery> Datei:Nrg lcd 1.jpg|Home-Screen mit Datum und Uhrzeit Datei:Nrg lcd 2.jpg|Aktueller Stromverbrauch Datei:Nrg lcd 3.jpg|Solardaten: Kollektortemperatur, Pumpenlast und Speichertemp. Datei:Nrg lcd 4.jpg|Debuginfos, Timeouts des TCP/IP-Stacks und Refresh des NTP-Clients </gallery> ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== [[Datei:Nrg json.png|thumb|Exemplarischer JSON-Datensatz]] Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= Aktuelle Firmware, EAGLE-Dateien des Shields (ohne V-Bus-Pegelwandler): [[Datei:Energieerfassung Firmware.zip]] =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Vcc auf GND) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann * [http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller * Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] 19cdad4c023c6ed723e2da4a7cc4d7a8a828b08f 553 549 2010-11-21T21:55:11Z Chris 2 Todos hinzugefügt, Fehler & Probleme etwas genauer beschrieben wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== [[Datei:Nrg hauptzaehler.jpg|thumb|Stromzähler mit aufgesetzter Erfassungseinheit]] Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[:wpde:Ferraris-Zähler|Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. [[Datei:Bananen Frucht.jpg|thumb|Eine Banane, eisenreich und sehr bekömmlich (cc:by-sa Darkone)]] Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. <gallery> Datei:Nrg zaehler umlauf.png|Ein Umlauf, wie er direkt am Fototransistor gemessen wird Datei:Nrg zaehler rauschen.png|"Grundrauschen" der rotierenden Scheibe (ohne DC-Offset) </gallery> Die Leistungsaufnahme lässt sich anhand der Umlaufzeit wie folgt berechnen: [[Datei:Nrg formel leistung.png]] Setzt man die im Screenshot ermittelten 42.6 Sekunden ein, erhält man eine Leistung von ~1127 Watt. Da die Leistung mit der Zeit exponentiell abnimmt, ist bei hohen Leistungsaufnahmen eine relativ hohe Auflösung der Zeit erforderlich. Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: <gallery> Datei:Nrg zaehler auswert.png|Auswerteschaltung Datei:Nrg zaehler pass.png|Zählersignal vor (blau) und nach (gelb) dem Filter </gallery> Links wird der Fototransistor in Sperrrichtung angeschlossen. Der 1µF-Elko und der nachfolgende 100k-Widerstand stellt einen Hochpass mit nicht näher definierter Grenzfrequenz (WolframAlpha sagt [http://www.wolframalpha.com/input/?i=1%2F%282*Pi*100kOhms*1%C2%B5F%29 1.592Hz]) dar. Die Frequenz ist ist im Hinblick auf [[:wpde:Hochpass:Ordnung]], Bauteiletoleranzen und der Zielfrequenz vermutlich nicht einmal ein Richtwert. Der folgende Hochpass hat eine Grenzfrequenz von ca. 16Hz. Hier gilt das gleiche Vertrauen wie in den Tiefpass. Aber alles kein Problem: Die Werte sind weitestgehend unkritisch. Es sind Umläufe im Millihertz-Bereich (also Umlaufdauern in der Größenordnung Sekunden bis Minuten) zu erwarten. Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. [[Datei:Nrg tarifzaehler.jpg|thumb|Tarifzähler, rechts das Fähnchen zum Anzeigen des Tarifs]] Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. [[Datei:Nrg_relais_freigabe.jpg|thumb|Relais für die Stromfreigabe, mit LED]] Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. '''Update 10.10.2010:''' Weasel (IRC) ist beim Anblick der Kennlinie der Temperatursensoren in der Anleitung des Vitosolic 200 blitzschnell darauf gekommen, dass es sich um PT500-Elemente handeln müssen, die jedoch nur für sehr teuer Geld erhältlich sind. Mein anfänglicher Scherz vonwegen 2 PT1000 parallel ergibt PT500 hat sich als gar nicht so dumm erwiesen: Idealerweise sind die Widerstände der Sensoren bei gleicher Temperatur ebenfalls gleich, Durch Parallelschaltung zweier PT1000 kann man sie problemlos an der PT1000 betreiben! Da ich sonst nichts mit meinen 9 Sensoren anzufangen wusste, fristen jetzt 8 dieser als 4 Fühler im Keller ihr dasein: Zwei erfassen die Ein- und Auslasstemperatur an der "Primärseite" der Wärmepumpe, einer sitzt im Warmwasserspeicher in oberster Schicht und der 4. misst (da mir noch nichts besseres einfiel) die Raumtemperatur im Heizkeller, die mangels Isolierung der Rohre deutlich zu hoch ist. ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. <gallery> Datei:Nrg shield.jpg|Shield des Großhirns Datei:Nrg grosshirn.jpg|Hirn von oben </gallery> ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. <gallery> Datei:Nrg lcd 1.jpg|Home-Screen mit Datum und Uhrzeit Datei:Nrg lcd 2.jpg|Aktueller Stromverbrauch Datei:Nrg lcd 3.jpg|Solardaten: Kollektortemperatur, Pumpenlast und Speichertemp. Datei:Nrg lcd 4.jpg|Debuginfos, Timeouts des TCP/IP-Stacks und Refresh des NTP-Clients </gallery> ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== [[Datei:Nrg json.png|thumb|Exemplarischer JSON-Datensatz]] Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= Aktuelle Firmware, EAGLE-Dateien des Shields (ohne V-Bus-Pegelwandler): [[Datei:Energieerfassung Firmware.zip]] =Nerviges/Todo= *Die interne Uhr hat eine sehr hohe Gangabweichung. Macht sich trotz kurzer NTP-Refresh-Intervallen bemerkbar *Der Speicher für die historischen Daten ist sehr klein. Bei Ausfall der Internetverbindung/Server/Cronjob gibt es zu schnell Lücken *Erfassung des Wasserzählers *Erfassung Außentemperatur =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Pads der LEDs zu groß und Widerstände gegen GND geschaltet) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann *[http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller *Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] 459e1110ba55ac8b13b84617721c39fc38fe8ade 569 553 2010-12-09T22:13:15Z Chris 2 /* Solaranlage */ Abschnitt Was kommt rein? wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== [[Datei:Nrg hauptzaehler.jpg|thumb|Stromzähler mit aufgesetzter Erfassungseinheit]] Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[:wpde:Ferraris-Zähler|Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. [[Datei:Bananen Frucht.jpg|thumb|Eine Banane, eisenreich und sehr bekömmlich (cc:by-sa Darkone)]] Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. <gallery> Datei:Nrg zaehler umlauf.png|Ein Umlauf, wie er direkt am Fototransistor gemessen wird Datei:Nrg zaehler rauschen.png|"Grundrauschen" der rotierenden Scheibe (ohne DC-Offset) </gallery> Die Leistungsaufnahme lässt sich anhand der Umlaufzeit wie folgt berechnen: [[Datei:Nrg formel leistung.png]] Setzt man die im Screenshot ermittelten 42.6 Sekunden ein, erhält man eine Leistung von ~1127 Watt. Da die Leistung mit der Zeit exponentiell abnimmt, ist bei hohen Leistungsaufnahmen eine relativ hohe Auflösung der Zeit erforderlich. Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: <gallery> Datei:Nrg zaehler auswert.png|Auswerteschaltung Datei:Nrg zaehler pass.png|Zählersignal vor (blau) und nach (gelb) dem Filter </gallery> Links wird der Fototransistor in Sperrrichtung angeschlossen. Der 1µF-Elko und der nachfolgende 100k-Widerstand stellt einen Hochpass mit nicht näher definierter Grenzfrequenz (WolframAlpha sagt [http://www.wolframalpha.com/input/?i=1%2F%282*Pi*100kOhms*1%C2%B5F%29 1.592Hz]) dar. Die Frequenz ist ist im Hinblick auf [[:wpde:Hochpass:Ordnung]], Bauteiletoleranzen und der Zielfrequenz vermutlich nicht einmal ein Richtwert. Der folgende Hochpass hat eine Grenzfrequenz von ca. 16Hz. Hier gilt das gleiche Vertrauen wie in den Tiefpass. Aber alles kein Problem: Die Werte sind weitestgehend unkritisch. Es sind Umläufe im Millihertz-Bereich (also Umlaufdauern in der Größenordnung Sekunden bis Minuten) zu erwarten. Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. [[Datei:Nrg tarifzaehler.jpg|thumb|Tarifzähler, rechts das Fähnchen zum Anzeigen des Tarifs]] Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. [[Datei:Nrg_relais_freigabe.jpg|thumb|Relais für die Stromfreigabe, mit LED]] Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. '''Update 10.10.2010:''' Weasel (IRC) ist beim Anblick der Kennlinie der Temperatursensoren in der Anleitung des Vitosolic 200 blitzschnell darauf gekommen, dass es sich um PT500-Elemente handeln müssen, die jedoch nur für sehr teuer Geld erhältlich sind. Mein anfänglicher Scherz vonwegen 2 PT1000 parallel ergibt PT500 hat sich als gar nicht so dumm erwiesen: Idealerweise sind die Widerstände der Sensoren bei gleicher Temperatur ebenfalls gleich, Durch Parallelschaltung zweier PT1000 kann man sie problemlos an der PT1000 betreiben! Da ich sonst nichts mit meinen 9 Sensoren anzufangen wusste, fristen jetzt 8 dieser als 4 Fühler im Keller ihr dasein: Zwei erfassen die Ein- und Auslasstemperatur an der "Primärseite" der Wärmepumpe, einer sitzt im Warmwasserspeicher in oberster Schicht und der 4. misst (da mir noch nichts besseres einfiel) die Raumtemperatur im Heizkeller, die mangels Isolierung der Rohre deutlich zu hoch ist. '''Update-Ende''' === Was kommt rein? === Auf der Unterseite [[Energieerfassung/Solarleistung]] habe ich beschrieben, wie man anhand einiger Parameter die Leistung der Solaranlage berechnen kann ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. <gallery> Datei:Nrg shield.jpg|Shield des Großhirns Datei:Nrg grosshirn.jpg|Hirn von oben </gallery> ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. <gallery> Datei:Nrg lcd 1.jpg|Home-Screen mit Datum und Uhrzeit Datei:Nrg lcd 2.jpg|Aktueller Stromverbrauch Datei:Nrg lcd 3.jpg|Solardaten: Kollektortemperatur, Pumpenlast und Speichertemp. Datei:Nrg lcd 4.jpg|Debuginfos, Timeouts des TCP/IP-Stacks und Refresh des NTP-Clients </gallery> ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== [[Datei:Nrg json.png|thumb|Exemplarischer JSON-Datensatz]] Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= Aktuelle Firmware, EAGLE-Dateien des Shields (ohne V-Bus-Pegelwandler): [[Datei:Energieerfassung Firmware.zip]] =Nerviges/Todo= *Die interne Uhr hat eine sehr hohe Gangabweichung. Macht sich trotz kurzer NTP-Refresh-Intervallen bemerkbar *Der Speicher für die historischen Daten ist sehr klein. Bei Ausfall der Internetverbindung/Server/Cronjob gibt es zu schnell Lücken *Erfassung des Wasserzählers *Erfassung Außentemperatur =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Pads der LEDs zu groß und Widerstände gegen GND geschaltet) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann *[http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller *Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] 6e699635cd23ff5635b4a036a62879f5d4ea555c Hauptseite 0 1 550 544 2010-11-15T19:46:39Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *10.10.2010 [[Kameratimer]] *31.08.2010 [[Energieerfassung]] *09.08.2010 [[AVR-NET-IO-Shield]] *15.07.2010 [[Nokia 5110 Displayadapter]] *09.07.2010 [[Sommerhitz]] *04.03.2010 [[VBus-Decoder]] =Updates= *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *01.09.2010 [[AVR-Doper]] unter Windows 7 *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) 187f95005c971423fcb795f64b1ea0d4d0c5f7e6 555 550 2010-11-21T22:10:26Z Chris 2 /* Updates */ wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *10.10.2010 [[Kameratimer]] *31.08.2010 [[Energieerfassung]] *09.08.2010 [[AVR-NET-IO-Shield]] *15.07.2010 [[Nokia 5110 Displayadapter]] *09.07.2010 [[Sommerhitz]] *04.03.2010 [[VBus-Decoder]] =Updates= *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll 2a030781b754155eb57908f451b611876aca27f4 570 555 2010-12-09T22:14:32Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *09.12.2010 [[Energieerfassung/Solarleistung]] *10.10.2010 [[Kameratimer]] *31.08.2010 [[Energieerfassung]] *09.08.2010 [[AVR-NET-IO-Shield]] *15.07.2010 [[Nokia 5110 Displayadapter]] *09.07.2010 [[Sommerhitz]] =Updates= *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll 3ca1aa80dc9a39b6a0f70f634d7f1c30edb38f47 588 570 2011-01-09T08:53:20Z Chris 2 /* Neues */ wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *09.01.2010 [[ASCII-Tabelle]] *09.12.2010 [[Energieerfassung/Solarleistung]] *10.10.2010 [[Kameratimer]] *31.08.2010 [[Energieerfassung]] *09.08.2010 [[AVR-NET-IO-Shield]] *15.07.2010 [[Nokia 5110 Displayadapter]] =Updates= *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll 8c7132ad2a7fbd86ee541fd79634a9d475abcebc 596 588 2011-01-15T15:30:04Z Robert 3 /* Neues */ wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *15.01.2011 [[Belichtungsgeraet]] *09.01.2010 [[ASCII-Tabelle]] *09.12.2010 [[Energieerfassung/Solarleistung]] *10.10.2010 [[Kameratimer]] *31.08.2010 [[Energieerfassung]] *09.08.2010 [[AVR-NET-IO-Shield]] *15.07.2010 [[Nokia 5110 Displayadapter]] =Updates= *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll f4f0a5ca6a2c55d949a8dad2ea044b9dd3da038b 610 596 2011-03-19T12:33:10Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *19.03.2011 [[Physik-Formelsammlung]] *15.01.2011 [[Belichtungsgeraet]] *09.01.2010 [[ASCII-Tabelle]] *09.12.2010 [[Energieerfassung/Solarleistung]] *10.10.2010 [[Kameratimer]] *31.08.2010 [[Energieerfassung]] =Updates= *19.03.2010 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll 1612d4bfa44f7c4e1703b1ecb91ca1c18ee79ef4 Datei:Avr-doper-registry.zip 6 195 551 2010-11-21T21:40:14Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 AVR-Doper 0 44 552 520 2010-11-21T21:44:25Z Chris 2 Patch AVR-Studio hinzugefügt wikitext text/x-wiki {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = C9 | FuseL = 9F }} Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Ich habe auch damit angefangen, eine SMD-Version der Platine zu machen, allerdings gibt es ein paar Platzprobleme (der ATMega in TQFP ist einfach zu klein für die ganzen Bauteile außen herum). Die Firmware wurde nicht verändert und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download des optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] =AVR-Doper unter Windows 7= Nachdem Windows XP schon etwas betagt ist und Vista eher ein flop war, steht man früher oder später an dem Punkt, Windows 7 zu verwenden. Zwar lassen sich die Vista-Treiber des AVR-Dopers unter Windows 7 installieren, AVR-Studio kann allerdings keine Verbindung zum Doper herstellen. Die Jungs von recursion.jp haben einen Treiber geschrieben, der sowohl unter Win7 x86 und Win7 x64 funktioniert: [http://www.recursion.jp/avrcdc/lowbulk.html http://www.recursion.jp/avrcdc/lowbulk.html] -> "avrcdc_inf.zip" Es kann sein, dass der Treiber manuell signiert werden muss (was bei meiner x86-Installation nicht erforderlich war). Nähere Informationen dazu (und auch der ursprüngliche Hinweis auf den Treiber) befinden sich im [http://forums.obdev.at/viewtopic.php?f=8&t=3591&p=12721#p12721 Forum von Objective Development] =Patch AVR-Studio= Wer den AVR-Doper direkt in Atmels AVR-Studio als STK500 benutzt, erhält bei jedem Herstellen der Verbindung eine nervige Fehlermeldung bezüglich der Firmware-Version. Ein kleiner Registry-Eintrag unterdrückt die Meldung: Unter HKEY_LOCAL_MACHINE\SOFTWARE\Atmel\AVRTools\STK500 muss VersionMajor auf 2 und VersionMinor auf 10 geändert werden. Für die, die den Registrierung-Editor nicht bedienen können oder möchten, gibt es eine passende Reg-Datei: [[Datei:Avr-doper-registry.zip]] [[Category:AVR]] [[Category:USB]] [[Category:PC]] 1f7cf037f9d8c860c7f1d3383c0e95450ca06004 580 552 2010-12-26T22:13:45Z Chris 2 /* Patch AVR-Studio */ Info zu x64 wikitext text/x-wiki {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = C9 | FuseL = 9F }} Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Ich habe auch damit angefangen, eine SMD-Version der Platine zu machen, allerdings gibt es ein paar Platzprobleme (der ATMega in TQFP ist einfach zu klein für die ganzen Bauteile außen herum). Die Firmware wurde nicht verändert und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download des optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] =AVR-Doper unter Windows 7= Nachdem Windows XP schon etwas betagt ist und Vista eher ein flop war, steht man früher oder später an dem Punkt, Windows 7 zu verwenden. Zwar lassen sich die Vista-Treiber des AVR-Dopers unter Windows 7 installieren, AVR-Studio kann allerdings keine Verbindung zum Doper herstellen. Die Jungs von recursion.jp haben einen Treiber geschrieben, der sowohl unter Win7 x86 und Win7 x64 funktioniert: [http://www.recursion.jp/avrcdc/lowbulk.html http://www.recursion.jp/avrcdc/lowbulk.html] -> "avrcdc_inf.zip" Es kann sein, dass der Treiber manuell signiert werden muss (was bei meiner x86-Installation nicht erforderlich war). Nähere Informationen dazu (und auch der ursprüngliche Hinweis auf den Treiber) befinden sich im [http://forums.obdev.at/viewtopic.php?f=8&t=3591&p=12721#p12721 Forum von Objective Development] =Patch AVR-Studio= Wer den AVR-Doper direkt in Atmels AVR-Studio als STK500 benutzt, erhält bei jedem Herstellen der Verbindung eine nervige Fehlermeldung bezüglich der Firmware-Version. Ein kleiner Registry-Eintrag unterdrückt die Meldung: Unter HKEY_LOCAL_MACHINE\SOFTWARE\Atmel\AVRTools\STK500 muss VersionMajor auf 0x00000002 (2) und VersionMinor auf 0x00000004 (4) geändert werden. Für die, die den Registrierung-Editor nicht bedienen können oder möchten, gibt es eine passende Reg-Datei: [[Datei:Avr-doper-registry.zip]] Wer sich die Tortur angetan hat und den Doper per virtuellem COM-Port an Vista/Win7 x64 zum laufen gebracht hat, muss die Änderung im Pfad HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Atmel\AVRTools\STK500 vornehmen. Also entweder in der .reg-Datei ändern oder manuell dort hin navigieren und bearbeiten. [[Category:AVR]] [[Category:USB]] [[Category:PC]] 46623b5a931866346defefa06f40c9ddf9f09d78 VBus-Decoder/FAQ 0 196 557 2010-12-08T07:50:30Z Chris 2 FAQ angelegt wikitext text/x-wiki '''Kann ich den Pegelwandler direkt an meinem Computer anschließen?''' Nein. Da der Pegelwandler mit TTL-Pegeln (0V/5V) arbeitet und die Schnittstelle am Computer mit RS232-Pegeln (+12V/-12V) arbeitet, muss ein weiterer Pegelwandler dazwischen. Ein MAX232 o.ä. übernimmt diese Aufgabe. Alternativ kann auch ein USB-UART-Converter verwendet à la Profilic PL2303 oder FTDI FT232. '''Ich habe eine Solaranlage von der Firma XYZ - kann ich sie mit deiner Schaltung/Software auslesen?''' Jein. Es kommt darauf an, welche Hardwareschnittstelle und welches Protokoll die Anlage verwendet. Steht Resol drauf, ist die Wahrscheinlichkeit hoch. Auch scheinen (neben meinem Regler) ein paar andere Regler von Viessman die gleiche Schnittstelle zu haben. Ich habe allerdings keinerlei Informationen, welcher Hersteller welche Schnittstelle welches Protokoll verwendet. Leider ;) dadd79d8b61499e6a5685fca2d3badffc910bb0d VBus-Decoder 0 120 558 532 2010-12-08T07:52:12Z Chris 2 FAQ hinzugefügt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die zwar Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <pre> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </pre> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <pre> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </pre> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Maschinen]] ebf67cd2372c203a74a0679ebad957b4ec195262 Datei:Netioshield pass.jpg 6 197 559 2010-12-09T20:52:18Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 AVR-NET-IO-Shield 0 166 560 502 2010-12-09T20:57:18Z Chris 2 wikitext text/x-wiki Seit einiger Zeit bietet Pollin mit dem [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] ein schönes Einsteigerboard für Netzwerkanwendungen an. Da es fast vollständig kompatibel zu Ulrich Radigs [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex Experimentier-Board] ist, lädt es zum Basteln und erweitern ein. Da das Board aufgrund des Preises und des einfachen Aufbaus recht beliebt ist, bietet Pollin mittlerweile auch ein Erweiterungsboard an. Leider hat das Original-Board und das Erweiterungsboard ein paar Schwachstellen: * Ineffiziente Stromversorgung (7805 und LM317) * Keine Absicherung gegen Kurzschlüsse/Überlast * Höherer Platzbedarf durch Erweiterungen (Grundfläche) * Lange Verbindungen zum Erweiterungsboard * Kein Platz für eigene Ideen Vor allem der erste und letzte Punkt haben mich etwas gestört. = Das Sandwich = [[Datei:Netioshield brd.png|thumb|Das Shields]] Inspiriert von den vielen Erweiterungen (Shields) des [http://arduino.cc/ Arduino] habe ich mich entschieden, eine Erweiterungsplatine im Sandwich-Stil zu entwerfen. Dieses soll direkt auf das Board des NET-IO gesteckt werden können und möglichst alle verfügbaren Pins für eigene Anwendungen zur Verfügung stellen. Die größte Schwierigkeit war, die korrekten Positionen der Bauteile zu finden. Dummerweise habe ich nach dem Bestellen des Bausatzes nicht daran gedacht, die Platine zu scannen. Mit Hilfe der Bauanleitung (die das Board leider nur verzerrt enthält), war es jedoch möglich, die Positionen halbwegs genau herauszufinden. Der optische Vergleich beider Boards und Aufdrücken der Platine auf einen Ausdruck war vielversprechend, absolute Klarheit kann aber nur eine produzierte Leiterkarte bringen. = Verbindung = Weitaus problematischer als das Layout zu zeichnen war das Finden passender Verbinder zwischen den Boards. Mein erster Gedanke war, beim DSub-25 einen stehenden Printstecker auf dem NET-IO und eine stehende Buchse auf dem Shield zu verbauen. Dadurch entsteht zwischen den Platinen allerdings ein Abstand von 20mm. Dazu kommt noch die mechanische Belastung beim Auseinanderziehen. Freiwillig macht man das nicht oft. Irgendwann kam ich auf die eigentlich naheliegende Idee, einen "normalen" Print-Steckverbinder zu nehmen und zum Verbinden der Boards zwei Buchsen für Flachbandkabel zu verwenden. Dadurch wird das Ganze zwar etwas länger, die mechanische Belastung beim Stecken wird aber minimiert. Als nächstes kommen die zwei Stiftleisten EXT und ISP. Normale Buchsenleisten sind zu kurz, um die Platinen zu verbinden. Meine Lösung war, kurze Kontaktbuchsen (SPL 64 bei Reichelt) auf die Buchsenleisten (8,5mm, BL 2x36G 2,54 bei Reichelt) zu stecken. Zusammen mit 15mm langen Abstandsbolzen zwischen den Platinen stehen die Stiftleisten noch einen knappen Millimeter beim Shield hinaus. Perfekt! Da es bei den übrigen Kontakten (unterhalb des AVR, UART und Stromversorgung) keine Stiftleisten "vorinstalliert" sind, bietet sich ein wenig Bastelei an. Wer großzügig die Preisangabe im Katalog abdeckt, kann bei Reichelt AW 226/20 und AW 122/20 bestellen. Alle anderen sollten lange Buchsenleisten möglichst mit gedrehten Kontakten (hat Reichelt nicht!) und Kontaktbuchsen (SPL 64 von Reichelt) haben: Zuerst muss man die Kontakte vom Plastik befreien. Wer nichts zum Auflösen des Kunststoffs zu Hause hat: Einfach an den Anrissen auseinanderzwicken, dadurch können die Kontakte besser herausgepult werden. Anschließend zwei kurze und einen langen Kontakt aufeinanderstecken, optional verlöten und in Schrumpfschlauch verpacken, fertig sind die Verbinder: <gallery> Datei:Buchsenleisten.jpg|Die verwendeten Leisten Datei:Buchsenleiste-knips.jpg|Auseinanderknipsen der Buchsenleisten Datei:Buchsenstifte.jpg|"Gewonnene" Stifte Datei:Netioshield kontakt.jpg|Zusammengesteckt und im verbauten Zustand </gallery> In die andere Platine muss dann nur noch ein Pin aus einer Stiftleiste. Am einfachsten geht es, wenn man alles zusammensteckt, zwischen die Platinen klemmt und mit wenig Zinn verlötet. Wenig Lötzinn deshalb, da sonst die Buchse gleich mit verlötet wird. Wer die beiden Platinen nicht mehr voneinander lösen will, kann auch einfach Drähte einsetzen. In diesem Fall ist es jedoch sehr empfehlenswert, einen zuverlässigen Bootloader zu verwenden oder die ISP-Pins freizuhalten bzw. zur Programmierung verwendbar zu schalten. = Stromversorgung = Mit dem Sandwich-Board war das Problem der Stromversorgung allerdings noch nicht erledigt. Die Wahl fiel auf die einfach (und für 5 sowie 3,3V gleichermaßen) erhältlichen [http://www.national.com/mpf/LM/LM2574.html LM2574]. Dieser braucht zwar aufgrund seiner vergleichsweise niedrigen Schaltfrequenz relativ große Induktivitäten, ist dafür aber ziemlich handzahm. Bei einer Versorgungsspannung von 12-16V sind bei beiden Wandlern lt. Datenblatt Induktivitäten mit 330µH gut geeignet. Um bei den Schaltreglern etwas an Bauhöhe zu sparen, kommen SMD-Spulen zum Einsatz. Aufgrund der großen Flächen ist ein Lötkolben mit >=80W und großer Lötspitze mehr als ratsam! Folgende Bauteile können auf dem NET-IO durch den Umbau weggelassen werden: D1, D2, D3, D4, D5, C1, C2, C3, C5, IC1, IC2, R1, R2 <gallery> Datei:Netioshield pwr brd.png|Das "Powershield" Datei:Netioshield power.jpg|Der relevante Part Datei:Netioshield pwr.png|überflüssige Bauteile </gallery> Zur Absicherung dient eine sich selbst rückstellende Polyfuse. Diese muss an die Eingangsspannung angepasst werden, da aufgrund der Schaltregler bei höheren Spannungen ein geringerer Strom fließt. Bei meinen groben Messungen kam die Schaltung auf etwa 1,6W. Bei einer Eingangsspannung von 12V (Spannungsabfall von ca. 1,4V am Gleichrichter beachten!) kann man daher mit einem Strombedarf von 150mA rechnen. Die Polyfuse kann man daher (ungeachtet der Verbraucher auf dem Shield) auf etwa 200mA dimensionieren. = Kollisionen = Beim Planen des eigenen Shields sollte man beim Platzieren von Bauteilen auf dem Bottom-Layer sehr vorsichtig sein, da es sehr schnell zu Kollisionen kommen kann. Insbesondere bei Kondensatoren und Buchsen muss man einen gewissen Abstand einplanen. Über der Netzwerkbuchse sollte man zudem keine bedrahteten Bauteile einsetzen, da die Chance von Kurzschlüssen hier mehr als hoch ist. Auch der Einsatz von SMD-Bauteilen auf der Unterseite des Shields bei der Netzwerkbuchse sollte vermieden werden. = Passgenauigkeit = Nachdem ich nun einen Scan der Platine habe, konnte ich die Passgenauigkeit prüfen. Lange Rede kurzer Sinn: die roten Punkte sind die Bohrungen im Shield: <gallery> Datei:Netioshield pass.jpg </gallery> Die Bohrungen sind also größtenteils erstaunlich genau. Lediglich beim Stromanschluss (Bohrungen für den Schraubendreher) und der SubD-25-Buchse hab ich mich ein wenig vertan. Korrektur folgt, sobald ich etwas Luft hab'. = Download = [[Datei:Netioshield.zip]] [[Kategorie:AVR]] 7c60af104643e90898bed1aa59043d6a6c9eb58c Datei:Solar schem.png 6 198 561 2010-12-09T21:13:37Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Solar spezwk.png 6 199 562 2010-12-09T21:15:54Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Solar wkap.png 6 200 563 2010-12-09T21:24:38Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Solar dichte.png 6 201 564 2010-12-09T21:48:27Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Solar masse.png 6 202 565 2010-12-09T21:50:44Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Solar formel.png 6 203 566 2010-12-09T21:56:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Solar feinheiten.png 6 204 567 2010-12-09T22:03:20Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Energieerfassung/Solarleistung 0 205 568 2010-12-09T22:11:00Z Chris 2 Die Seite wurde neu angelegt: „[[Datei:Solar schem.png|thumb]] Die Erfassung der Betriebsdaten ist schön und gut. Solange man sie nicht richtig auswerten kann passiert eigentlich nicht viel, a…“ wikitext text/x-wiki [[Datei:Solar schem.png|thumb]] Die Erfassung der Betriebsdaten ist schön und gut. Solange man sie nicht richtig auswerten kann passiert eigentlich nicht viel, außer dass die Datenbank immer größer wird. Mein mittelfristiges Ziel der Energieerfassung ist zu ermitteln, was reingeht und was rauskommt. [[Energieerfassung#W.C3.A4rme_Extrem|Letzteres]] habe ich ja (zumindest vorerst) zurückgestellt. Ersteres kann ich mittlerweile zumindest teilweise machen. Die Solaranlage basiert drauf, dass die in den Kollektoren aufgefangene Energie in thermische umgewandelt wird um sie dann im Wärmetauscher dem Heizkreislauf zuzuführen. Im Groben sieht das dann so aus, wie rechts im Bild zu sehen ist. Aber wie viel Energie ist es denn? Die Physik bietet hierfür die [[wpde:Spezifische Wärmekapazität|spezifische Wärmekapazität]] als Lösung an: [[Datei:Solar spezwk.png]] ΔQ ist die Energie, die der Materie (also dem Wärmeträger) zugefügt oder entnommen wurde, c die spezifische Wärmekapazität und ΔT die Temperaturdifferenz beim zufügen oder entnehmen der Energie. Man benötigt also nur drei Parameter um herauszufinden, wie viel Energie dem Heizkreislauf zugefügt wurde. In unserer Solaranlage wird das Wärmeträger "Tyfocor® G-LS" verwendet. Im Datenblatt dazu (Veröffentlichung an dieser Stelle muss ich noch klären) ist die spezifische Wärmekapazität als lineare Kurve angegeben. Über die Punktsteigungsform lässt sie sich mit folgender Formel ermitteln: [[Datei:Solar wkap.png]] Fehlt nur noch die Masse der Flüssigkeit. Das wird schon ein bisschen kniffeliger. Laut unserem Heizungsbauer sind - wenn ich mich richtig erinnere - 6 Liter der Brühe in der Anlage. Diese Information hilft aber recht wenig, da man ja nur interessiert, was im Wärmetauscher vor sich geht. Die Angabe der zum System zugeführten Energie für die meisten ein eher nichtssagender Wert. Ich könnte jedem auf der Straße erzählen, dass in meinem Puffer 80 Joule gespeichert sind ohne dass sie merken, dass man damit nicht einmal einen kleinen Eiswürfel schmelzen könnte. Mit Leistung kann aber jeder etwas anfangen. Mit einem Wasserkocher mit 2000 Watt dauert es vielleicht drei Minuten, bis ein Liter Wasser kocht. Damit kann jeder etwas anfangen. Hinter dieser Angabe steckt nichts anderes als die Energie - 2000W * 180s sind 360000Ws. Wattsekunden entsprechen gleichzeitig Joule. Viola - Energie! Eines muss ich vorweg sagen: Den letzten Abschnitt habe ich ein bisschen hingedreht. Tatsächlich kommt bei der Berechnung eine Leistung in Watt heraus, obwohl bei der oben genannten Formel eine Energieänderung das Ergebnis ist. Der Hintergrund hierfür ist, dass die Flüssigkeit im System nicht steht, sondern sich bewegt. Zunächst gilt es aber herauszufinden, wie viel Masse die bewegte Flüssigkeit hat. Die Dichte ist ebenso im Datenblatt vermerkt. Leider handelt es sich hier nicht um eine lineare Abhängigkeit zur Temperatur. Da sich die unlinearität allerdings in Grenzen hält (und ich ehrlich gesagt keine Lust auf eine Ausgleichsrechnung hatte), wird die Dichte mit folgender Formel angenähert: [[Datei:Solar dichte.png]] Über die Dichte kann man in Verbindung mit dem Volumen die Masse der Flüssigkeit berechnen, [[Datei:Solar masse.png]] wo wir schon beim nächsten Problem wären: Wie viel Volumen ist im Wärmetauscher oder besser - wie viel geht da durch? Glücklicherweise ist im Primärkreis der Solaranlage ein Strömungsmesser angebracht, der den Durchfluss in Liter pro Minute angibt. Mit einer kleinen Umrechnung kommt man auf die [[wpde:Si-Einheit|Si-Einheit]] m³/s, womit man wieder schön rechnen kann. Leider kann man den Durchfluss nicht direkt aus der Pumpenleistung berechnen, da damit mehrere Faktoren (z. B. thermische Konvektion) zusammenhängen. Um zumindest einen Richtwert zu erhalten, habe ich die Werte des Durchflusses für verschiedene Pumpenleistungen notiert. Der Durchfluss wird momentan über eine Lookup-Table ermittelt. Sobald ich mehrere Werte habe, werden diese natürlich mit in die Formel gepackt. Zusammengesetzt ergibt sich aus den einzelnen Formeln folgendes Gebilde: [[Datei:Solar formel.png]] Theoretisch bräuchte man bei der Bestimmung der Dichte und spezifischen Wärmekapazität unendlich viele Werte, da die Temperatur des Mediums im Wärmetauscher abnimmt. Da ich hier jedoch nicht mit Integralen um mich werfen will, habe ich den Wärmetauscher als unendlich klein definiert und den Mittelwert der Ein- und Ausgangstemperatur verwendet. Das ist zwar nicht zwangsläufig korrekt, sollte aber eine (für diese Anwendung) brauchbare Annäherung an die Wirklichkeit sein (Mann, hört sich das wissenschaftlich an...). Mit der Einheitenkontrolle wird geprüft, dass die Formel keine groben Schnitzer hat: [[Datei:Solar feinheiten.png]] Alle Werte kürzen sich - ich bin zufrieden! Nimmt man die Zeit (t) auf die linke Seite, ergibt sich die Leistung in kW - was will man mehr? Fehlt nur noch die Probe auf Exempel - sind reale Werte von der Solaranlage plausibel? Eingesetzt, ausgerechnet: ja! Eine Tabelle muss ich noch erstellen und hochladen, aber es sieht ziemlich gut aus. 4957a24fe1e7610a8682aac2f7d6ec3b0db28e15 Datei:Ascii-Tabelle Ausschnitt.png 6 212 581 2011-01-09T08:42:34Z Chris 2 Ausschnitt aus der ASCII-Tabelle wikitext text/x-wiki Ausschnitt aus der ASCII-Tabelle 4063910f2d5163a0c9f233b2381471714e68fcbd 586 581 2011-01-09T08:51:15Z Qsysopr 1 hat „[[Datei:Ascii-Tabelle Auschnitt.png]]“ nach „[[Datei:Ascii-Tabelle Ausschnitt.png]]“ verschoben: weil ich zu doof für korrekte Rechtschreibung bin wikitext text/x-wiki Ausschnitt aus der ASCII-Tabelle 4063910f2d5163a0c9f233b2381471714e68fcbd Datei:ASCII-Tabelle.pdf 6 213 582 2011-01-09T08:43:50Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 ASCII-Tabelle 0 214 583 2011-01-09T08:44:22Z Chris 2 Die Seite wurde neu angelegt: „[[Datei:Ascii-Tabelle Ausschnitt.png|thumb|Ausschnitt aus der ASCII-Tabelle]] Beim Programmieren ist der Besitz einer [wpde:ASCII-Tabelle|ASCII-Tabelle] oft sehr …“ wikitext text/x-wiki [[Datei:Ascii-Tabelle Ausschnitt.png|thumb|Ausschnitt aus der ASCII-Tabelle]] Beim Programmieren ist der Besitz einer [wpde:ASCII-Tabelle|ASCII-Tabelle] oft sehr praktisch. Nur leider habe ich bis noch keine gefunden, die das bietet, was ich will. Deshalb habe ich die Textverarbeitung aktiviert und mich daran gemacht, eine eigene ASCII-Tabelle zu entwerfen. Die Tabelle umfasst zwei Seiten. Wer nur den "normalen" Zeichensatz benötigt, druckt die erste Seite, wer den erweiterten Satz möchte, druckt sich entsprechend beide. Rund um die Tabelle sind die Binäranteile jeder Teile und Spalte abgedruckt, sodass man vom Binärcode relativ schnell zum Zeichen finden kann. In den Kästchen selbst findet sich zum einen das Zeichen selbst, die binäre und darunter die dezimale (links) und hexadezimale (rechts) Entsprechung. Da man die Steuerzeichen auf Papier direkt nicht richtig abbilden kann, sind die Ensprechungen in Kurzform abgedruckt. Zusätzlich befindet sich darunter (sofern vorhanden) die aus Kommandozeilen bekannte Caret-Notation sowie die Escape-Codes aus C-oiden Sprachen. =Download= [[Datei:ASCII-Tabelle.pdf]] 554af7e178bdc5912dc652a5e36730b5e8579b2c 584 583 2011-01-09T08:45:46Z Chris 2 Der geneigte Leser weiß es schon: Kategorie vergessen wikitext text/x-wiki [[Datei:Ascii-Tabelle Ausschnitt.png|thumb|Ausschnitt aus der ASCII-Tabelle]] Beim Programmieren ist der Besitz einer [[wpde:ASCII-Tabelle|ASCII-Tabelle]] oft sehr praktisch. Nur leider habe ich bis noch keine gefunden, die das bietet, was ich will. Deshalb habe ich die Textverarbeitung aktiviert und mich daran gemacht, eine eigene ASCII-Tabelle zu entwerfen. Die Tabelle umfasst zwei Seiten. Wer nur den "normalen" Zeichensatz benötigt, druckt die erste Seite, wer den erweiterten Satz möchte, druckt sich entsprechend beide. Rund um die Tabelle sind die Binäranteile jeder Teile und Spalte abgedruckt, sodass man vom Binärcode relativ schnell zum Zeichen finden kann. In den Kästchen selbst findet sich zum einen das Zeichen selbst, die binäre und darunter die dezimale (links) und hexadezimale (rechts) Entsprechung. Da man die Steuerzeichen auf Papier direkt nicht richtig abbilden kann, sind die Ensprechungen in Kurzform abgedruckt. Zusätzlich befindet sich darunter (sofern vorhanden) die aus Kommandozeilen bekannte Caret-Notation sowie die Escape-Codes aus C-oiden Sprachen. =Download= [[Datei:ASCII-Tabelle.pdf]] [[Category:Sonstiges]] 282e77f2cd2cbdf72a76c2a326515e6e4b072c7a 585 584 2011-01-09T08:47:07Z Chris 2 wikitext text/x-wiki [[Bild:Ascii-Tabelle Ausschnitt.png|thumb|Ausschnitt aus der ASCII-Tabelle]] Beim Programmieren ist der Besitz einer [[wpde:ASCII-Tabelle|ASCII-Tabelle]] oft sehr praktisch. Nur leider habe ich bis noch keine gefunden, die das bietet, was ich will. Deshalb habe ich die Textverarbeitung aktiviert und mich daran gemacht, eine eigene ASCII-Tabelle zu entwerfen. Die Tabelle umfasst zwei Seiten. Wer nur den "normalen" Zeichensatz benötigt, druckt die erste Seite, wer den erweiterten Satz möchte, druckt sich entsprechend beide. Rund um die Tabelle sind die Binäranteile jeder Teile und Spalte abgedruckt, sodass man vom Binärcode relativ schnell zum Zeichen finden kann. In den Kästchen selbst findet sich zum einen das Zeichen selbst, die binäre und darunter die dezimale (links) und hexadezimale (rechts) Entsprechung. Da man die Steuerzeichen auf Papier direkt nicht richtig abbilden kann, sind die Ensprechungen in Kurzform abgedruckt. Zusätzlich befindet sich darunter (sofern vorhanden) die aus Kommandozeilen bekannte Caret-Notation sowie die Escape-Codes aus C-oiden Sprachen. =Download= [[Datei:ASCII-Tabelle.pdf]] [[Category:Sonstiges]] 3cc1ba22ffd24715c8f2cafd010c8d0dbf93d57b Datei:Ascii-Tabelle Auschnitt.png 6 215 587 2011-01-09T08:51:15Z Qsysopr 1 hat „[[Datei:Ascii-Tabelle Auschnitt.png]]“ nach „[[Datei:Ascii-Tabelle Ausschnitt.png]]“ verschoben: weil ich zu doof für korrekte Rechtschreibung bin wikitext text/x-wiki #WEITERLEITUNG [[Datei:Ascii-Tabelle Ausschnitt.png]] 9d048e02cfb14684ddd6f7e5e21b4c3fa62d330a Datei:ECL-Oszi1.png 6 222 599 2011-02-17T22:17:32Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:ECL-Oszi2.png 6 223 600 2011-02-17T22:18:45Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:ECL-eca60-sch.png 6 224 601 2011-02-17T22:47:44Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 603 601 2011-02-20T12:53:26Z Chris 2 hat eine neue Version von „[[Datei:ECL-eca60-sch.png]]“ hochgeladen wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 ECL-Bus-Decoder 0 225 602 2011-02-17T23:05:34Z Chris 2 Die Seite wurde neu angelegt: „ Da mir die Betriebsdatenerfassung unserer Wärmepumpe, die den zum Raumleitgerät zugehörigen Regler verwendet, nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|ko…“ wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe, die den zum Raumleitgerät zugehörigen Regler verwendet, nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. In der Bedienungsanleitung der Anlage entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung zu finden war. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine brauchbaren Ergebnisse - also schnappte ich mir das Oszilloskop und versuchte auf eigene Faust, dem Teil etwas zu entlocken: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 70Hz Rechtecksignal, in dessen Low-Phasen Daten übertragen werden. Dass es ein Wechselsignal ist, lässt vermuten, dass die Designer ein gleichanteilsfreies Signal erzielen wollten, was ein paar Vorteile bringt. Wenn man es genau nimmt, ist der Rechteck übertragungstechnisch zwar suboptimal, allerdings kann man dadurch die "eingebetteten" Daten wesentlich einfacher rekonstruieren. Nutzinformationen selbst werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Dabei ist die Bitlänge etwa 0,4ms, was einer Frequenz von 2,5kHz entspricht. In dem Zeitfenster von 7ms können also Brutto 17 Bits übertragen werden. Da ich mit meinem Oszilloskop leider kein vollständiges Datenpaket einfangen konnte und mein Logic-Analyzer wohl auch zu kurzspeichrig ist, werde ich wohl einen alten PC als primitivst-Oszi verwenden, zumal die Frequenzen für die Soundkarte kein Problem darstellen sollten. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: (TODO) Mit etwas Buntstift und überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Allerdings irritieren mich die Widerstandswerte sowie die etwas eigenwillige Beschaltung rund um T1 und T2. (Ich glaub, da muss ich nochmal den Stromlaufplan mit der Originalschaltung vergleichen...) f84acd91145698f4660851a5cedd63fd0192a8af 606 602 2011-02-20T13:13:16Z Chris 2 Platinenfotos, korrigierter Stromlaufplan Bus-Interface wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe, die den zum Raumleitgerät zugehörigen Regler verwendet, nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. In der Bedienungsanleitung der Anlage entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung zu finden war. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine brauchbaren Ergebnisse - also schnappte ich mir das Oszilloskop und versuchte auf eigene Faust, dem Teil etwas zu entlocken: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Nutzinformationen selbst werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. In dessen Low-Phasen (7,28ms) werden die Daten mit einer Bitlänge von 428µs übertragen. Also können in dieser Zeit 17 Bit übertragen werden, wobei das erste immer 0 ist. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und mein Logic-Analyzer wohl auch zu kurzspeichrig ist, werde ich wohl einen alten PC als primitivst-Oszi verwenden, zumal die Frequenzen für die Soundkarte kein Problem darstellen sollten. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-top.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis mir aufgefallen ist, dass da zur Spannungsglättung noch ein Elko an der Schaltung hängt. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals. Wie T3 zum Senden von Daten verwendet werden soll, ist mir bis jetzt noch etwas schleierhaft. Bei den gemessenen 27Vss Busspannung würden die 48kOhm einen Strom von etwa 550µA verursachen. Der dürfte die Versorgungsspannung nur einbrechen lassen, wenn ihr Strom sehr stark begrenzt wird (was ich etwas bezweifel). 6b29abeb74a50bf370b4a4de11ceec2a8f95a860 615 606 2011-03-21T22:45:31Z Chris 2 ein paar Infos zum Phy wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-top.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis mir aufgefallen ist, dass da zur Spannungsglättung noch ein Elko an der Schaltung hängt. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals. Über T3 kann der Bus (der übrigens mit knapp 27Vss getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. In der Bedienungsanleitung der Anlage entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine brauchbaren Ergebnisse - da der ECA60 an dem Bus so wunderbar funktioniert, wird kurzerhand das Oszilloskop angeschlossen: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. In dessen Low-Phasen werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Also können in dieser Zeit 17 Bit übertragen werden, wobei das erste immer 0 ist. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und der Logic Analyzer daran angeschlossen. Nach einer Woche gespannter Leitung durchs halbe Haus habe ich selbige durch Leerrohre gelegt. Aus Toleranz wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} 3c12082bbebf8c0e85eb02885551116ec2128646 617 615 2011-03-22T19:50:08Z Chris 2 wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-top.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27Vss getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine brauchbaren Ergebnisse - da der ECA60 an dem Bus so wunderbar funktioniert, wird kurzerhand das Oszilloskop angeschlossen: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. In dessen Low-Phasen werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus Toleranz wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, [[Datei:Ecl protokollyse.c|half]] ein AVR (Atmega8 mit 12MHz) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene TEilpaket und aktiviert den Timer mit halbem Bit Wartezeit. Im Timer0-Interrupt wird nun insgesamt 18 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 18. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden ganz grob die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. Auf der PC-Seite werkelt [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 E00502 584002 282602 DEC602 6E1A02 000000 000000 000000 000000 5E0900 5E1400 000000 000000 D81B00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils sogar periodisch! Beim weiteren Durchsuchen finden sich folgende Paketköpfe/Adressen: E00502, FCC502, DEC100, 5E0B00, F40D02, E00302, 5E0900, 5E1300, F41302 und 5E2300. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> 5E0B00 FE5100 540000 000200 0C1A00 F40D02 005002 54FE03 FE0302 A21A02 5E0B00 FE5500 540000 000200 101A00 F40D02 005402 54FE03 FE0302 A61A02 5E0900 8A1500 000000 000000 041B00 5E1300 020000 000000 000000 721B00 F41302 1EFE03 FE0302 FC0102 1E1A02 FCC502 FEFF03 FEFF03 000002 B81A02 5E0B00 FE5900 540000 000200 141A00 F40D02 005802 54FE03 FE0302 AA1A02 DEC100 BE2400 EC1200 460000 C41A00 DEC100 DE3400 00C000 8A0000 FA1A00 E00302 3E0802 F44502 000002 601A02 E00502 304A02 262C02 DE4602 D41B02 5E0B00 FE5D00 540000 000200 181A00 F40D02 005C02 54FE03 FE0302 AE1A02 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen 5E0B00 und F40D02. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Dort stehen für 5E0B00 die Werte 51, 55, 59 und 5D. In Dezimalschreibweise 81, 85, 89 und 93. Schiebt man diese Werte um 2 Byte nach rechts (ganzzahlig durch 4 dividieren), erhält man die eingestellten Temperaturen. F40D02 scheint die Rückmeldung vom Regler zu sein, der die gesetzte Temperatur bestätigt. Die Analyse und Auswertung findet mit mehreren PHP-Scripts (dreckig aber schnell) statt. 89b4cb68227d6c343430d6e343d33044aa99e8e8 Datei:ECL ECA60-bot.jpg 6 226 604 2011-02-20T12:58:11Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:ECL ECA60-top.jpg 6 227 605 2011-02-20T12:58:24Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Physik-Formelsammlung.pdf 6 228 607 2011-03-19T12:06:32Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Physik-Formelsammlung 0 229 608 2011-03-19T12:26:39Z Chris 2 Die Seite wurde neu angelegt: „Irgendwann im ersten Semester bin ich auf die Idee gekommen, eine Formelsammlung für Physik zu schreiben, die genau die Anforderungen für die Klausur entspricht…“ wikitext text/x-wiki Irgendwann im ersten Semester bin ich auf die Idee gekommen, eine Formelsammlung für Physik zu schreiben, die genau die Anforderungen für die Klausur entspricht. Markus (ein Kommilitone) hat sie im zweiten Semester fortgeführt und ich schließlich ergänzt. = Inhalt = Die Formelsammlung umfasst so ziemlich alles, was man in den ersten beiden Semstern Physik im Studiengang Elektrotechnik (zumindest an der Hochschule Ulm) benötigt. Dies ist u. a.: # Grundlagen ## Die wichtigsten Werte auf einen Blick ## Atom ## Additionstheoreme # Punktmechanik ## Kinematik ### Geradlinige Bewegung (Translation) ### Gleichmäßig beschleunigte Bewegung (Translation) ### Würfe (Translation) ### Kreisbewegung (Rotation) ### Übersetzungstabelle Translation ? Rotation ## Dynamik ### Impulssatz (Translation) ### Kraftbegriff ### Kräfte ### Trägheitskräfte ## Energie ### Begriffe ### Stöße ## Himmelsmechanik # Mechanik der starren Körper ## Statik ### Gleichgewichtsbedingung ### Schwerpunkt ## Dynamik starrer Körper ### Schwerpunktbewegung # Materie in Feldern ## Elektrisches Feld ### Allgemein ### Dipol ### Kondensator ### Schaltvorgänge ### Dielektrika ### Leitende Materialien ### Leitung in Flüssigkeit ### Leitung in Gasen ## Magnetisches Feld ### Analogie ## Bewegung im homogenen Feld ## Lange gerade Leiter ## Verschieden Leiter ### Allgemein ### Lange Spule (Solenoid)/Toroidspule (Ring) ### Mitte einer Kreisschleife/Kurze Spule (L«D) ### Beliebige Spule ## Magnetisches Dipolmoment (Spin, Eigendrehimpuls eines Atoms) ### Kenngrößen ### Hall-Effekt # Induktion ## Induktionsgesetz ## Anwendungen ## Schaltvorgänge # Schwingungen ## Harmonischer Oszillator ### Pohlsches Rad ## Gedämpfte Schwingung ### Mechanisch ### Elektrisch ## Schwinger mit Anregung # Wellen ## Grundwissen ## Polarisation ## Wellengleichung ## Dopplereffekt ## Stehende Welle ## Interferenz und Beugung am Spalt ## Wellenoptik ## Dipolstrahlung ### Nahfeld ### Fernfeld # Statistik ## Gastherorie # Quantenphysik ## Allgemein ## Materialwellen ## Gebundene Zustände ## Wasserstoffatom ### Wichtige Energieübergänge ## Bändermodell ### Eigenhalbleiter ### Dotierte Halbleiter # Festkörper ## Halbleiter ### Homogene Halbleiter ### Heterogene Halbleiter = Download = Obwohl wir und unsere Dozenten gründlich gearbeitet werden, können wir keine Garantie für die Richtigkeit übernehmen. Solltest du Fehler finden, lass es [[Benutzer:Chris|mich]] bitte wissen. [[Datei:Physik-Formelsammlung.pdf]] (Stand: 19.03.2011) [[Kategorie:Sonstiges]] 6ab2ad5bf3c217c84f926c3cf5abba33f74e6529 611 608 2011-03-19T14:14:17Z Chris 2 Typo wikitext text/x-wiki Irgendwann im ersten Semester bin ich auf die Idee gekommen, eine Formelsammlung für Physik zu schreiben, die genau die Anforderungen für die Klausur entspricht. Markus (ein Kommilitone) hat sie im zweiten Semester fortgeführt und ich schließlich ergänzt. = Inhalt = Die Formelsammlung umfasst so ziemlich alles, was man in den ersten beiden Semstern Physik im Studiengang Elektrotechnik (zumindest an der Hochschule Ulm) benötigt. Dies ist u. a.: # Grundlagen ## Die wichtigsten Werte auf einen Blick ## Atom ## Additionstheoreme # Punktmechanik ## Kinematik ### Geradlinige Bewegung (Translation) ### Gleichmäßig beschleunigte Bewegung (Translation) ### Würfe (Translation) ### Kreisbewegung (Rotation) ### Übersetzungstabelle Translation ? Rotation ## Dynamik ### Impulssatz (Translation) ### Kraftbegriff ### Kräfte ### Trägheitskräfte ## Energie ### Begriffe ### Stöße ## Himmelsmechanik # Mechanik der starren Körper ## Statik ### Gleichgewichtsbedingung ### Schwerpunkt ## Dynamik starrer Körper ### Schwerpunktbewegung # Materie in Feldern ## Elektrisches Feld ### Allgemein ### Dipol ### Kondensator ### Schaltvorgänge ### Dielektrika ### Leitende Materialien ### Leitung in Flüssigkeit ### Leitung in Gasen ## Magnetisches Feld ### Analogie ## Bewegung im homogenen Feld ## Lange gerade Leiter ## Verschieden Leiter ### Allgemein ### Lange Spule (Solenoid)/Toroidspule (Ring) ### Mitte einer Kreisschleife/Kurze Spule (L«D) ### Beliebige Spule ## Magnetisches Dipolmoment (Spin, Eigendrehimpuls eines Atoms) ### Kenngrößen ### Hall-Effekt # Induktion ## Induktionsgesetz ## Anwendungen ## Schaltvorgänge # Schwingungen ## Harmonischer Oszillator ### Pohlsches Rad ## Gedämpfte Schwingung ### Mechanisch ### Elektrisch ## Schwinger mit Anregung # Wellen ## Grundwissen ## Polarisation ## Wellengleichung ## Dopplereffekt ## Stehende Welle ## Interferenz und Beugung am Spalt ## Wellenoptik ## Dipolstrahlung ### Nahfeld ### Fernfeld # Statistik ## Gastherorie # Quantenphysik ## Allgemein ## Materialwellen ## Gebundene Zustände ## Wasserstoffatom ### Wichtige Energieübergänge ## Bändermodell ### Eigenhalbleiter ### Dotierte Halbleiter # Festkörper ## Halbleiter ### Homogene Halbleiter ### Heterogene Halbleiter = Download = Obwohl wir und unsere Dozenten gründlich gearbeitet haben, können wir keine Garantie für die Richtigkeit übernehmen. Solltest du Fehler finden, lass es [[Benutzer:Chris|mich]] bitte wissen. [[Datei:Physik-Formelsammlung.pdf]] (Stand: 19.03.2011) [[Kategorie:Sonstiges]] ac4ce7bea7823d7304b7a37dcf4fc4cf6101d3da Benutzer:Chris 2 45 612 364 2011-03-19T14:23:38Z Chris 2 wikitext text/x-wiki Tjo, das ist es also, mein ganz privater Bereich auf hobbyelektronik.org. Ich bin Chris und quasi der Schöpfer von der Homepage hier. Irgendwann in diesem Jahrhundert (lt. Archive.org Ende 2003) fing ich damit an, meine mehr oder weniger gelungenen Bastel-Projekte auf hobby-elektronik.de.vu zu veröffentlichen. Damals noch bei Tripod. Der Speicherplatz wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich irgendwann, auf das schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10 April 2005 die Domain hobbyelektronik.org gekauft. Zu .org kam es, da mir eine Woche davor jemand die .net-Domain "geklaut" hat. Im Nachhinein bin ich glücklich um diesen Zustand - damit bin ich/sind wir dem .NET-Hype vollkommen entgangen. Eine richtige Organisation sind wir zwar noch immer nicht aber das kann ja noch werden ;) Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" (oder so ähnlich) schimpfen. Seit Oktober 2009 bin ich Student der Elektrotechnik/Nachrichtentechnik an der [http://www.hs-ulm.de Hochschule Ulm]. = Hobbys = * Elektronik ** Digitales (analoge Schaltungen sind mir irgendwie unheimlich *g*) ** Alles, das irgendwas anzeigt ** AVRs ** Sensoren ** Interfaces (v. a. zum PC) * Programmieren ** C# ** PHP ** JavaScript (mit allem Drum und Dran) ** C (für AVRs) = Kontakt = Solltest du Fragen, Kritik, Verbesserungsvorschläge haben oder einen Fehler gefunden haben - zögere nicht und schreib' einfach eine E-Mail an mich: chris at hobbyelektronik punkt org (siehe auch [[Hobbyelektronik.org:Impressum|Impressum]]) 763edc34cff4da5e1207b5a7708bbbf62d951dc0 Datei:Ecl la1.png 6 230 613 2011-03-21T22:35:55Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl la2.png 6 231 614 2011-03-21T22:39:39Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl protokollyse.c 6 232 616 2011-03-22T18:02:29Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 ECL-Bus-Decoder 0 225 618 617 2011-04-10T21:46:59Z Chris 2 wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-top.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils sogar periodisch! Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0600, AF0900, AF1100, EF6000, F00101, F00201, FA0501, FA0601, FA0901, FE6201 und FF0501. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> (vorübergehend leer) </pre> In dieser Sequenz wurde die Temperatur zuerst auf ..., dann auf ..., ... und ...°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen ... und ... . Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (1 Nibble)><Empfänger (1 Nibble)><Befehl (1 Byte)><Befehl vom Master (1 Bit)> Nach näherer Analyse der Daten ergab sich folgende Geräteliste {| class="wikitable" |- ! Adresse !! Überschrift |- | 0 || Broadcast |- | A || Raumleitgerät '''ECA 60''' |- | E || Alarm- und Temperaturüberwachungsmodul '''ECA 86''' |- | F || Regler '''ECL 300''' |} 5634bd965cedc51f312462109d0e3bff29fe5299 621 618 2011-04-12T17:27:25Z Chris 2 Paketinformationen hinzugefügt wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-top.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: {| class="wikitable" |- ! Adresse !! Überschrift |- | 0 || Broadcast |- | A || Raumleitgerät '''ECA 60''' |- | E || Alarm- und Temperaturüberwachungsmodul '''ECA 86''' |- | F || Regler '''ECL 300''' |} == Pakete == {| class="wikitable" |- ! Sender/Empfänger !! Typ !! Bezeichnung |- | AF || 04 || Innentemperatur (ECA 60) |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) |- | AF || 09 || Abfrage Tagesprogramm |- | EF || 60 || Temperaturfühler ECA 86 |- | F0 || 01 || Außentemperatur|-| F0 || 02 || Aktuelle Zeit |- | FA || 05 || Solltemperatur am ECL 300 setzen |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) |- | FA || 09 || Tagesprogramm (Antwort auf AF06) |- | FE || 62 || Setzen Relais an ECA 86 |} == AF04 (Innentemperatur) == Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 </pre> Im zweiten Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im ersten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[1] + b[0]/128 berechnet e48ed28557fd3e7fb622d0407a89d381cb279d36 623 621 2011-04-12T17:51:23Z Chris 2 wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-top.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung |- | AF || 04 || Innentemperatur (ECA 60) |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) |- | AF || 09 || Abfrage Tagesprogramm |- | EF || 60 || Temperaturfühler ECA 86 |- | F0 || 01 || Außentemperatur |- | F0 || 02 || Aktuelle Zeit |- | FA || 05 || Solltemperatur am ECL 300 setzen |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) |- | FA || 09 || Tagesprogramm (Antwort auf AF06) |- | FE || 62 || Setzen Relais an ECA 86 |} In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 </pre> Im zweiten Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im ersten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[1] + b[0]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger. 435a1a7d38cda833455195427996c1b41dd9e4a3 627 623 2011-04-19T21:19:48Z Chris 2 typo wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-top.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung |- | AF || 04 || Innentemperatur (ECA 60) |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) |- | AF || 09 || Abfrage Tagesprogramm |- | EF || 60 || Temperaturfühler ECA 86 |- | F0 || 01 || Außentemperatur |- | F0 || 02 || Aktuelle Zeit |- | FA || 05 || Solltemperatur am ECL 300 setzen |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) |- | FA || 09 || Tagesprogramm (Antwort auf AF06) |- | FE || 62 || Setzen Relais an ECA 86 |} In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 </pre> Im zweiten Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im ersten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[1] + b[0]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger. === AF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? 00000000 !!!!!!!0 !00000!! </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das erste Byte bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. Im zweiten Byte befindet sich die Solltemperatur um ein Bit verschoben (b[1] >> 1). Das dritte Byte hat sich mir ebenso noch nicht offenbart, weitere Untersuchungen sind vermutlich notwendig. Im 5. Byte ist die Temperaturabweichung zur aktuellen Solltemperatur notiert, die für eine gewisse Dauer (Stunden bzw. Tage) gültig ist. Dabei muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Manuell sieht die Berechnung wie folgt aus: <pre> diff = b[4] >> 1; if(diff & 0x40 == 0x40) { diff ^= 0x7F; diff = (diff + 1) * -1; } </pre> Das letzte (6.) Byte dient teilweise der Signalisierung, um welche Art der temporären Abweichung es sich handelt. Dazu werden die untersten beiden Bits betrachtet: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Unbekannter Status |- | 01 || 1 || keine Sonderzeit |- | 10 || 2 || Entspannen/Temperaturerhöhung |- | 11 || 3 || Abwesenheit/Temperaturabsenkung |} Ist zusätzlich das höchste Bit im 6. Byte gesetzt, handelt es sich um eine kurzweilige Abweichung (Stundenbereich), andernfalls um eine über mehrere Tage hinweg. Das Setzen einer Vorübergehenden Abweichung ist im Allgemeien etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. 70208ea1cdddbaaf87f24d0f19c319c890e9e328 630 627 2011-04-23T21:44:21Z Chris 2 das hab ich doch schon korrigiert?! spinnt Mediawiki? wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung |- | AF || 04 || Innentemperatur (ECA 60) |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) |- | AF || 09 || Abfrage Tagesprogramm |- | EF || 60 || Temperaturfühler ECA 86 |- | F0 || 01 || Außentemperatur |- | F0 || 02 || Aktuelle Zeit |- | FA || 05 || Solltemperatur am ECL 300 setzen |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) |- | FA || 09 || Tagesprogramm (Antwort auf AF06) |- | FE || 62 || Setzen Relais an ECA 86 |} In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 </pre> Im zweiten Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im ersten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[1] + b[0]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger. === AF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? 00000000 !!!!!!!0 !00000!! </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das erste Byte bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. Im zweiten Byte befindet sich die Solltemperatur um ein Bit verschoben (b[1] >> 1). Das dritte Byte hat sich mir ebenso noch nicht offenbart, weitere Untersuchungen sind vermutlich notwendig. Im 5. Byte ist die Temperaturabweichung zur aktuellen Solltemperatur notiert, die für eine gewisse Dauer (Stunden bzw. Tage) gültig ist. Dabei muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Manuell sieht die Berechnung wie folgt aus: <pre> diff = b[4] >> 1; if(diff & 0x40 == 0x40) { diff ^= 0x7F; diff = (diff + 1) * -1; } </pre> Das letzte (6.) Byte dient teilweise der Signalisierung, um welche Art der temporären Abweichung es sich handelt. Dazu werden die untersten beiden Bits betrachtet: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Unbekannter Status |- | 01 || 1 || keine Sonderzeit |- | 10 || 2 || Entspannen/Temperaturerhöhung |- | 11 || 3 || Abwesenheit/Temperaturabsenkung |} Ist zusätzlich das höchste Bit im 6. Byte gesetzt, handelt es sich um eine kurzweilige Abweichung (Stundenbereich), andernfalls um eine über mehrere Tage hinweg. Das Setzen einer Vorübergehenden Abweichung ist im Allgemeien etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. 1ddc1d22176cf2ba192cf0f6fd1d929ce1bf14da 631 630 2011-04-23T22:18:13Z Chris 2 wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung |- | AF || 04 || Innentemperatur (ECA 60) |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) |- | AF || 09 || Abfrage Tagesprogramm |- | EF || 60 || Temperaturfühler ECA 86 |- | F0 || 01 || Außentemperatur |- | F0 || 02 || Aktuelle Zeit |- | FA || 05 || Solltemperatur am ECL 300 setzen |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) |- | FA || 09 || Tagesprogramm (Antwort auf AF06) |- | FE || 62 || Setzen Relais an ECA 86 |} In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 Temperatur </pre> Im zweiten Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im ersten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[1] + b[0]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger. === AF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? 00000000 !!!!!!!0 !00000!! Soltmp. Abw.tmp. Modus </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das erste Byte bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. '''Solltemperatur''' Im zweiten Byte befindet sich die Solltemperatur um ein Bit verschoben (b[1] >> 1). Das dritte Byte hat sich mir ebenso noch nicht offenbart, weitere Untersuchungen sind vermutlich notwendig. '''Abweichende Temperatur''' Im 5. Byte ist die Temperaturabweichung zur aktuellen Solltemperatur notiert, die für eine gewisse Dauer (Stunden bzw. Tage) gültig ist. Dabei muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Manuell sieht die Berechnung wie folgt aus: <pre> diff = b[4] >> 1; if(diff & 0x40 == 0x40) { diff ^= 0x7F; diff = (diff + 1) * -1; } </pre> '''Abweichungsart''' Das letzte (6.) Byte dient teilweise der Signalisierung, um welche Art der temporären Abweichung es sich handelt. Dazu werden die untersten beiden Bits betrachtet: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Unbekannter Status |- | 01 || 1 || keine Sonderzeit |- | 10 || 2 || Entspannen/Temperaturerhöhung |- | 11 || 3 || Abwesenheit/Temperaturabsenkung |} <strike>Ist zusätzlich das höchste Bit im 6. Byte gesetzt, handelt es sich um eine kurzweilige Abweichung (Stundenbereich), andernfalls um eine über mehrere Tage hinweg.</strike> Das Setzen einer Vorübergehenden Abweichung ist im Allgemeien etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. === AF/FA09 (Tagesprogramm) === Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen. Um diese Daten zu erhalten, muss es folgendes auf den Bus legen: <pre> AF09 00000010 00000000 00000000 00000000 00000000 00000000 00000!!! 00000000 00000000 00000000 00000000 00000000 Tag </pre> Die untersten 3 Bit entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6. Der ECL300 antwortet dann wie folgt: <pre> FA09 00001111 11111111 11111111 11111111 11110000 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ^ 23:30 00:00 ^ </pre> Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet. In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr. === EF60 (Temperatursensoren ECA86) === Zur Erweiterung der Mess- und Steuermöglichkeiten ist in unserer Heizung das Modul ECA86 verbaut. Es kann 4 Pt1000 Temperatursensoren auslesen und zwei Kontakte steuern. Die Werte der Temperatursensoren werden zyklisch alle 30 Sekunden in zwei Paketen gesendet: <pre> EF60 10000001 00011110 011010000 00001001 001000011 00000000 EF60 01110101 00011111 000000000 01100000 010000101 00000000 !!!!!!!! !!!!!!!! !!!!!!!!! !!!!!!!! !!!!!!!!! 00000000 Temperatur Bx/x Temperatur Bx/x Index </pre> Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt. Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes des Pakets nach der Adresse, der zweite in den beiden darauf folgenden. Das 6. Byte gibt an, um welche Werte es sich handelt. 421459a6fbef2f273c0dea7b7ba42096d5075a0f 635 631 2011-04-28T08:10:29Z Chris 2 Intervalle der Pakete hinzugefügt, Erläuterung Positionsangaben wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung !! Häufigkeit |- | AF || 04 || Innentemperatur (ECA 60) || 125/h |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || -- |- | AF || 09 || Abfrage Tagesprogramm || 63/h |- | EF || 60 || Temperaturfühler ECA 86 || 125/h |- | F0 || 01 || Außentemperatur || 125/h |- | F0 || 02 || Aktuelle Zeit || 125/h |- | FA || 05 || Solltemperatur am ECL 300 setzen || -- |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) || -- |- | FA || 09 || Tagesprogramm (Antwort auf AF06) || 63/h |- | FE || 62 || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine Stunde, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. Die Positionsangaben (b[x]) beziehen sich auf die Position nach den Adress-/Befehl-Bytes. Mit b[0] ist also das erste Byte nach Adresse und Befehl gemeint. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 Temperatur </pre> Im zweiten Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im ersten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[1] + b[0]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger (siehe Diagramm). === AF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? 00000000 !!!!!!!0 !00000!! Soltmp. Abw.tmp. Modus </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das erste Byte bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. ==== Solltemperatur ==== Im zweiten Byte befindet sich die Solltemperatur um ein Bit verschoben (b[1] >> 1). Das dritte Byte hat sich mir ebenso noch nicht offenbart, weitere Untersuchungen sind vermutlich notwendig. ==== Abweichende Temperatur ==== Im 5. Byte ist die Temperaturabweichung zur aktuellen Solltemperatur notiert, die für eine gewisse Dauer (Stunden bzw. Tage) gültig ist. Dabei muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Manuell sieht die Berechnung wie folgt aus: <pre> diff = b[4] >> 1; if(diff & 0x40 == 0x40) { diff ^= 0x7F; diff = (diff + 1) * -1; } </pre> ==== Abweichungsart ==== Das letzte (6.) Byte dient teilweise der Signalisierung, um welche Art der temporären Abweichung es sich handelt. Dazu werden die untersten beiden Bits betrachtet: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Unbekannter Status |- | 01 || 1 || keine Sonderzeit |- | 10 || 2 || Entspannen/Temperaturerhöhung |- | 11 || 3 || Abwesenheit/Temperaturabsenkung |} <strike>Ist zusätzlich das höchste Bit im 6. Byte gesetzt, handelt es sich um eine kurzweilige Abweichung (Stundenbereich), andernfalls um eine über mehrere Tage hinweg.</strike> Das Setzen einer Vorübergehenden Abweichung ist im Allgemeien etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. === AF/FA09 (Tagesprogramm) === Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen. Um diese Daten zu erhalten, muss es folgendes auf den Bus legen: <pre> AF09 00000010 00000000 00000000 00000000 00000000 00000000 00000!!! 00000000 00000000 00000000 00000000 00000000 Tag </pre> Die untersten 3 Bit entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6. Der ECL300 antwortet dann wie folgt: <pre> FA09 00001111 11111111 11111111 11111111 11110000 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ^ 23:30 00:00 ^ </pre> Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet. In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr. === EF60 (Temperatursensoren ECA86) === Zur Erweiterung der Mess- und Steuermöglichkeiten ist in unserer Heizung das Modul ECA86 verbaut. Es kann 4 Pt1000 Temperatursensoren auslesen und zwei Kontakte steuern. Die Werte der Temperatursensoren werden zyklisch alle 30 Sekunden in zwei Paketen gesendet: <pre> EF60 10000001 00011110 011010000 00001001 001000011 00000000 EF60 01110101 00011111 000000000 01100000 010000101 00000000 !!!!!!!! !!!!!!!! !!!!!!!!! !!!!!!!! !!!!!!!!! 00000000 Temperatur Bx/x Temperatur Bx/x Index </pre> Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt. Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes des Pakets nach der Adresse, der zweite in den beiden darauf folgenden. Das 6. Byte gibt an, um welche Werte es sich handelt. 11abe15232de6c1378fb5a03647e4e68e45de3ff 636 635 2011-04-28T08:14:48Z Chris 2 Abschnitt erstellt, Bilder hinzugefügt wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: === Busteilnehmer === {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} <gallery> Datei:Ecl300.jpg|ECL 300 Datei:Eca86.jpg|ECA 86 Datei:Eca60.jpg|ECA 60 </gallery> == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung !! Häufigkeit |- | AF || 04 || Innentemperatur (ECA 60) || 125/h |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || -- |- | AF || 09 || Abfrage Tagesprogramm || 63/h |- | EF || 60 || Temperaturfühler ECA 86 || 125/h |- | F0 || 01 || Außentemperatur || 125/h |- | F0 || 02 || Aktuelle Zeit || 125/h |- | FA || 05 || Solltemperatur am ECL 300 setzen || -- |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) || -- |- | FA || 09 || Tagesprogramm (Antwort auf AF06) || 63/h |- | FE || 62 || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine Stunde, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. Die Positionsangaben (b[x]) beziehen sich auf die Position nach den Adress-/Befehl-Bytes. Mit b[0] ist also das erste Byte nach Adresse und Befehl gemeint. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 Temperatur </pre> Im zweiten Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im ersten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[1] + b[0]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger (siehe Diagramm). === AF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? 00000000 !!!!!!!0 !00000!! Soltmp. Abw.tmp. Modus </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das erste Byte bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. ==== Solltemperatur ==== Im zweiten Byte befindet sich die Solltemperatur um ein Bit verschoben (b[1] >> 1). Das dritte Byte hat sich mir ebenso noch nicht offenbart, weitere Untersuchungen sind vermutlich notwendig. ==== Abweichende Temperatur ==== Im 5. Byte ist die Temperaturabweichung zur aktuellen Solltemperatur notiert, die für eine gewisse Dauer (Stunden bzw. Tage) gültig ist. Dabei muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Manuell sieht die Berechnung wie folgt aus: <pre> diff = b[4] >> 1; if(diff & 0x40 == 0x40) { diff ^= 0x7F; diff = (diff + 1) * -1; } </pre> ==== Abweichungsart ==== Das letzte (6.) Byte dient teilweise der Signalisierung, um welche Art der temporären Abweichung es sich handelt. Dazu werden die untersten beiden Bits betrachtet: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Unbekannter Status |- | 01 || 1 || keine Sonderzeit |- | 10 || 2 || Entspannen/Temperaturerhöhung |- | 11 || 3 || Abwesenheit/Temperaturabsenkung |} <strike>Ist zusätzlich das höchste Bit im 6. Byte gesetzt, handelt es sich um eine kurzweilige Abweichung (Stundenbereich), andernfalls um eine über mehrere Tage hinweg.</strike> Das Setzen einer Vorübergehenden Abweichung ist im Allgemeien etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. === AF/FA09 (Tagesprogramm) === Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen. Um diese Daten zu erhalten, muss es folgendes auf den Bus legen: <pre> AF09 00000010 00000000 00000000 00000000 00000000 00000000 00000!!! 00000000 00000000 00000000 00000000 00000000 Tag </pre> Die untersten 3 Bit entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6. Der ECL300 antwortet dann wie folgt: <pre> FA09 00001111 11111111 11111111 11111111 11110000 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ^ 23:30 00:00 ^ </pre> Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet. In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr. === EF60 (Temperatursensoren ECA86) === Zur Erweiterung der Mess- und Steuermöglichkeiten ist in unserer Heizung das Modul ECA86 verbaut. Es kann 4 Pt1000 Temperatursensoren auslesen und zwei Kontakte steuern. Die Werte der Temperatursensoren werden zyklisch alle 30 Sekunden in zwei Paketen gesendet: <pre> EF60 10000001 00011110 011010000 00001001 001000011 00000000 EF60 01110101 00011111 000000000 01100000 010000101 00000000 !!!!!!!! !!!!!!!! !!!!!!!!! !!!!!!!! !!!!!!!!! 00000000 Temperatur Bx/x Temperatur Bx/x Index </pre> Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt. Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes des Pakets nach der Adresse, der zweite in den beiden darauf folgenden. Das 6. Byte gibt an, um welche Werte es sich handelt. 740a9bdb4af08f6081d3db840cf3a06b60a6f577 637 636 2011-04-28T08:43:35Z Chris 2 Beschreibung zu den Busteilnehmern hinzugefügt wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: == Busteilnehmer == {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} === ECL 300 === [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Das/Der ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. [http://de.fernwaerme.danfoss.com/xxTypex/17613_MNU17407525_SIT21.html Produktseite bei Danfoss] === ECA 86 === [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt [http://de.fernwaerme.danfoss.com/Product/087B1158_MNU17407526.html Produktseite bei Danfoss] === ECA 60 === [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren werkelt ein HD6473837 von Renesas. [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407525.html Produktseite bei Danfoss] == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung !! Häufigkeit |- | AF || 04 || Innentemperatur (ECA 60) || 125/h |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || -- |- | AF || 09 || Abfrage Tagesprogramm || 63/h |- | EF || 60 || Temperaturfühler ECA 86 || 125/h |- | F0 || 01 || Außentemperatur || 125/h |- | F0 || 02 || Aktuelle Zeit || 125/h |- | FA || 05 || Solltemperatur am ECL 300 setzen || -- |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) || -- |- | FA || 09 || Tagesprogramm (Antwort auf AF06) || 63/h |- | FE || 62 || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine Stunde, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. Die Positionsangaben (b[x]) beziehen sich auf die Position nach den Adress-/Befehl-Bytes. Mit b[0] ist also das erste Byte nach Adresse und Befehl gemeint. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 Temperatur </pre> Im zweiten Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im ersten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[1] + b[0]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger (siehe Diagramm). === AF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? 00000000 !!!!!!!0 !00000!! Soltmp. Abw.tmp. Modus </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das erste Byte bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. ==== Solltemperatur ==== Im zweiten Byte befindet sich die Solltemperatur um ein Bit verschoben (b[1] >> 1). Das dritte Byte hat sich mir ebenso noch nicht offenbart, weitere Untersuchungen sind vermutlich notwendig. ==== Abweichende Temperatur ==== Im 5. Byte ist die Temperaturabweichung zur aktuellen Solltemperatur notiert, die für eine gewisse Dauer (Stunden bzw. Tage) gültig ist. Dabei muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Manuell sieht die Berechnung wie folgt aus: <pre> diff = b[4] >> 1; if(diff & 0x40 == 0x40) { diff ^= 0x7F; diff = (diff + 1) * -1; } </pre> ==== Abweichungsart ==== Das letzte (6.) Byte dient teilweise der Signalisierung, um welche Art der temporären Abweichung es sich handelt. Dazu werden die untersten beiden Bits betrachtet: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Unbekannter Status |- | 01 || 1 || keine Sonderzeit |- | 10 || 2 || Entspannen/Temperaturerhöhung |- | 11 || 3 || Abwesenheit/Temperaturabsenkung |} <strike>Ist zusätzlich das höchste Bit im 6. Byte gesetzt, handelt es sich um eine kurzweilige Abweichung (Stundenbereich), andernfalls um eine über mehrere Tage hinweg.</strike> Das Setzen einer Vorübergehenden Abweichung ist im Allgemeien etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. === AF/FA09 (Tagesprogramm) === Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen. Um diese Daten zu erhalten, muss es folgendes auf den Bus legen: <pre> AF09 00000010 00000000 00000000 00000000 00000000 00000000 00000!!! 00000000 00000000 00000000 00000000 00000000 Tag </pre> Die untersten 3 Bit entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6. Der ECL300 antwortet dann wie folgt: <pre> FA09 00001111 11111111 11111111 11111111 11110000 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ^ 23:30 00:00 ^ </pre> Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet. In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr. === EF60 (Temperatursensoren ECA86) === <pre> EF60 10000001 00011110 011010000 00001001 001000011 00000000 EF60 01110101 00011111 000000000 01100000 010000101 00000000 !!!!!!!! !!!!!!!! !!!!!!!!! !!!!!!!! !!!!!!!!! 00000000 Temperatur Bx/x Temperatur Bx/x Index </pre> Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt. Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes des Pakets nach der Adresse, der zweite in den beiden darauf folgenden. Das 6. Byte gibt an, um welche Werte es sich handelt. 06b85835f1e29e98e29049a008ee01a23201b8b6 638 637 2011-04-29T08:48:37Z Chris 2 verschiedenes wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: == Busteilnehmer == {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} === ECL 300 === [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Das/Der ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. Auf der Vorderseite befindet sich eine Diagnoseschnittstelle, die als RS232 mit 1200 Baud, 8 Bit, Odd Parity und 2 Stoppbits spricht. Der Stecker ist ein RJ12 (6P6C), die Anschlussbelegung für den PC lautet wie folgt: {| class="wikitable"|-! RJ12 !! Sub-D|-| 4 Rx || 3|-| 5 Tx || 2|-| 7 GND || 5|} Achtung: Die Zählweise beim RJ12-Stecker beginnt bei 2. Aufgrund der mäßigen Beschreibung im Datenblatt kann es sein, dass die Belegung gespiegelt ist (werde ich noch prüfen) Das Auslesen findet "aktiv" statt, d. h. man muss Werte abfragen - der Regler sendet von sich aus nichts. Zum Abfragen der Temperaturen muss man 0xCE <addr> 0x00 0x00 <checksum> senden. Für die Checksum muss man alle gesendeten Bytes ver-XOR-en, für die Temperaturen also einfach 0xCE ^ addr. (Adresstabelle) [http://de.fernwaerme.danfoss.com/xxTypex/17613_MNU17407525_SIT21.html Produktseite bei Danfoss] === ECA 86 === [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt [http://de.fernwaerme.danfoss.com/Product/087B1158_MNU17407526.html Produktseite bei Danfoss] === ECA 60 === [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEProm 93C66A (512x8 bit) gespeichert. [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407525.html Produktseite bei Danfoss] == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung !! Häufigkeit |- | AF || 04 || Innentemperatur (ECA 60) || 125/h |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || -- |- | AF || 09 || Abfrage Tagesprogramm || 63/h |- | EF || 60 || Temperaturfühler ECA 86 || 125/h |- | F0 || 01 || Außentemperatur || 125/h |- | F0 || 02 || Aktuelle Zeit || 125/h |- | FA || 05 || Solltemperatur am ECL 300 setzen || -- |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) || -- |- | FA || 09 || Tagesprogramm (Antwort auf AF06) || 63/h |- | FE || 62 || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine Stunde, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. Die Positionsangaben (b[x]) beziehen sich auf die Position nach den Adress-/Befehl-Bytes. Mit b[0] ist also das erste Byte nach Adresse und Befehl gemeint. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 Temperatur </pre> Im zweiten Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im ersten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[1] + b[0]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger (siehe Diagramm). === AF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? 00000000 !!!!!!!0 !00000!! Soltmp. Abw.tmp. Modus </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das erste Byte bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. ==== Solltemperatur ==== Im zweiten Byte befindet sich die Solltemperatur um ein Bit verschoben (b[1] >> 1). Das dritte Byte hat sich mir ebenso noch nicht offenbart, weitere Untersuchungen sind vermutlich notwendig. ==== Abweichende Temperatur ==== Im 5. Byte ist die Temperaturabweichung zur aktuellen Solltemperatur notiert, die für eine gewisse Dauer (Stunden bzw. Tage) gültig ist. Dabei muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Manuell sieht die Berechnung wie folgt aus: <pre> diff = b[4] >> 1; if(diff & 0x40 == 0x40) { diff ^= 0x7F; diff = (diff + 1) * -1; } </pre> ==== Abweichungsart ==== Das letzte (6.) Byte dient teilweise der Signalisierung, um welche Art der temporären Abweichung es sich handelt. Dazu werden die untersten beiden Bits betrachtet: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Unbekannter Status |- | 01 || 1 || keine Sonderzeit |- | 10 || 2 || Entspannen/Temperaturerhöhung |- | 11 || 3 || Abwesenheit/Temperaturabsenkung |} <strike>Ist zusätzlich das höchste Bit im 6. Byte gesetzt, handelt es sich um eine kurzweilige Abweichung (Stundenbereich), andernfalls um eine über mehrere Tage hinweg.</strike> Das Setzen einer Vorübergehenden Abweichung ist im Allgemeien etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. === AF/FA09 (Tagesprogramm) === Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen. Um diese Daten zu erhalten, muss es folgendes auf den Bus legen: <pre> AF09 00000010 00000000 00000000 00000000 00000000 00000000 00000!!! 00000000 00000000 00000000 00000000 00000000 Tag </pre> Die untersten 3 Bit entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6. Der ECL300 antwortet dann wie folgt: <pre> FA09 00001111 11111111 11111111 11111111 11110000 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ^ 23:30 00:00 ^ </pre> Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet. In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr. === EF60 (Temperatursensoren ECA86) === <pre> EF60 10000001 00011110 011010000 00001001 001000011 00000000 EF60 01110101 00011111 000000000 01100000 010000101 00000000 !!!!!!!! !!!!!!!! !!!!!!!!! !!!!!!!! !!!!!!!!! 00000000 Temperatur Bx/x Temperatur Bx/x Index </pre> Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt. Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes des Pakets nach der Adresse, der zweite in den beiden darauf folgenden. Das 6. Byte gibt an, um welche Werte es sich handelt. == Prüfsumme == Wie bereits im [http://hobbyelektronik.org/b/?p=415 Blog] bemängelt ist die Prüfsumme nicht allzu solide. Sie wird berechnet, indem alle Bytes des Pakets exklusive der vorletzten beiden miteinander addiert (!) werden und mit 0xFF verundet werden. Diese "Prüfsumme" entspricht dem vorletzten Byte des Pakets, wobei es manchmal vorkommt, dass das MSB gekippt ist (näherer Grund ist noch unbekannt). Das letzte Paket im Byte ist immer 0x0D, was zur Synchronisierung verwendet werden kann. == Was fehlt noch? == === Störung === Seitdem ich die Daten erfasse hatte ich leider/zum Glück noch keine Störung der Anlage. Ich könnte sie zwar am Alarmmodul künstlich erzeugen, war bisher aber noch nicht mutig/dumm genug. Laut Installateur werden Störungen auf dem ECA60 angezeigt, deshalb liegt sehr nahe, dass diese auch über den Bus übertragen werden. === Aktives Auslesen === Dass das aktive Auslesen von Parametern funktioniert, zeigt das ECA 60 mit dem aktuellen Tagesprogramm. Geht das auch mit anderen Werten? = Download = Folgt :-) b2aded11f35dd1ca8303cf3ddbb41850f41a8644 639 638 2011-05-03T20:10:15Z Chris 2 Adresstabelle Debug hinzugefügt, Adresstabelle ECL-Bus ergänzt, Beschreibung korrigiert wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: == Busteilnehmer == {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} === ECL 300 === [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Das/Der ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. Auf der Vorderseite befindet sich eine Diagnoseschnittstelle, die als RS232 mit 1200 Baud, 8 Bit, Odd Parity und 2 Stoppbits spricht. Der Stecker ist ein RJ12 (6P6C), die Anschlussbelegung für den PC lautet wie folgt: {| class="wikitable" |- ! RJ12 !! Sub-D |- | 4 Rx || 3 |- | 5 Tx || 2 |- | 7 GND || 5 |} Achtung: Die Zählweise beim RJ12-Stecker beginnt bei 2. Aufgrund der mäßigen Beschreibung im Datenblatt kann es sein, dass die Belegung gespiegelt ist (werde ich noch prüfen) Das Auslesen findet "aktiv" statt, d. h. man muss Werte abfragen - der Regler sendet von sich aus nichts. Zum Abfragen der Temperaturen muss man 0xCE <addr> 0x00 0x00 <checksum> senden. Für die Checksum muss man alle gesendeten Bytes ver-XOR-en, für die Temperaturen also einfach 0xCE ^ addr. {| class="wikitable" |- ! Adresse !! Anschluss |- | 0xFA || B8 |- | 0x32 || B5 |- | 0x34 || B4 ? |- | 0xF8 || B3 ? |- | 0xFC || B7 ? |- | 0x38 || B2 |- | 0x3C || B1 |} [http://de.fernwaerme.danfoss.com/xxTypex/17613_MNU17407525_SIT21.html Produktseite bei Danfoss] === ECA 86 === [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt [http://de.fernwaerme.danfoss.com/Product/087B1158_MNU17407526.html Produktseite bei Danfoss] === ECA 60 === [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEProm 93C66A (512x8 bit) gespeichert. [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407525.html Produktseite bei Danfoss] == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung !! Häufigkeit |- | AF || 04 || Innentemperatur (ECA 60) || 125/h |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || -- |- | AF || 09 || Abfrage Tagesprogramm || 63/h |- | AF || 11 || Zeit setzen || -- |- | EF || 60 || Temperaturfühler ECA 86 || 125/h |- | F0 || 01 || Außentemperatur || 125/h |- | F0 || 02 || Aktuelle Zeit || 125/h |- | FA || 05 || Solltemperatur am ECL 300 setzen || -- |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) || -- |- | FA || 09 || Tagesprogramm (Antwort auf AF06) || 63/h |- | FE || 62 || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine Stunde, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. Die Positionsangaben b[x] beziehen sich auf den 0-basierenden Index im Paket, die Angabe "das x-te Byte" auf die 1-basierende Position. Das Byte zu Beginn eines Pakets ist also b[0] und wird mit "1. Byte" bezeichnet. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 Temperatur </pre> Im zweiten Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im ersten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[1] + b[0]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger (siehe Diagramm). === AF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? 00000000 !!!!!!!0 ?00000!! Soltmp. Abw.tmp. Modus </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das dritte Byte (b[2]) bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. ==== Solltemperatur ==== Im zweiten Byte befindet sich die Solltemperatur um ein Bit verschoben (b[1] >> 1). Das dritte Byte hat sich mir ebenso noch nicht offenbart, weitere Untersuchungen sind vermutlich notwendig. ==== Abweichende Temperatur ==== Im 5. Byte ist die Temperaturabweichung zur aktuellen Solltemperatur notiert, die für eine gewisse Dauer (Stunden bzw. Tage) gültig ist. Dabei muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Manuell sieht die Berechnung wie folgt aus: <pre> diff = b[4] >> 1; if(diff & 0x40 == 0x40) { diff ^= 0x7F; diff = (diff + 1) * -1; } </pre> ==== Abweichungsart ==== Das letzte (6.) Byte dient teilweise der Signalisierung, um welche Art der temporären Abweichung es sich handelt. Dazu werden die untersten beiden Bits betrachtet: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Unbekannter Status |- | 01 || 1 || keine Sonderzeit |- | 10 || 2 || Entspannen/Temperaturerhöhung |- | 11 || 3 || Abwesenheit/Temperaturabsenkung |} <strike>Ist zusätzlich das höchste Bit im 6. Byte gesetzt, handelt es sich um eine kurzweilige Abweichung (Stundenbereich), andernfalls um eine über mehrere Tage hinweg.</strike> Das Setzen einer Vorübergehenden Abweichung ist im Allgemeien etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. === AF/FA09 (Tagesprogramm) === Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen. Um diese Daten zu erhalten, muss es folgendes auf den Bus legen: <pre> AF09 00000010 00000000 00000000 00000000 00000000 00000000 00000!!! 00000000 00000000 00000000 00000000 00000000 Tag </pre> Die untersten 3 Bit entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6. Der ECL300 antwortet dann wie folgt: <pre> FA09 00001111 11111111 11111111 11111111 11110000 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ^ 23:30 00:00 ^ </pre> Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet. In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr. === EF60 (Temperatursensoren ECA86) === <pre> EF60 10000001 00011110 011010000 00001001 001000011 00000000 EF60 01110101 00011111 000000000 01100000 010000101 00000000 !!!!!!!! !!!!!!!! !!!!!!!!! !!!!!!!! !!!!!!!!! 00000000 Temperatur Bx/x Temperatur Bx/x Index </pre> Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt. Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes des Pakets nach der Adresse, der zweite in den beiden darauf folgenden. Das 6. Byte gibt an, um welche Werte es sich handelt. == Prüfsumme == Wie bereits im [http://hobbyelektronik.org/b/?p=415 Blog] bemängelt ist die Prüfsumme nicht allzu solide. Sie wird berechnet, indem alle Bytes des Pakets exklusive der vorletzten beiden miteinander addiert (!) werden und mit 0xFF verundet werden. Diese "Prüfsumme" entspricht dem vorletzten Byte des Pakets, wobei es manchmal vorkommt, dass das MSB gekippt ist (näherer Grund ist noch unbekannt). Das letzte Paket im Byte ist immer 0x0D, was zur Synchronisierung verwendet werden kann. == Was fehlt noch? == === Störung === Seitdem ich die Daten erfasse hatte ich leider/zum Glück noch keine Störung der Anlage. Ich könnte sie zwar am Alarmmodul künstlich erzeugen, war bisher aber noch nicht mutig/dumm genug. Laut Installateur werden Störungen auf dem ECA60 angezeigt, deshalb liegt sehr nahe, dass diese auch über den Bus übertragen werden. === Aktives Auslesen === Dass das aktive Auslesen von Parametern funktioniert, zeigt das ECA 60 mit dem aktuellen Tagesprogramm. Geht das auch mit anderen Werten? = Download = Folgt :-) 8b1370c74e8af822da66ad9f6916261f1dfcceaa 640 639 2011-05-03T21:41:35Z Chris 2 Ich nähere mich dem Ziel... wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: == Busteilnehmer == {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} === ECL 300 === [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Das/Der ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. Auf der Vorderseite befindet sich eine Diagnoseschnittstelle, die als RS232 mit 1200 Baud, 8 Bit, Odd Parity und 2 Stoppbits spricht. Der Stecker ist ein RJ12 (6P6C), die Anschlussbelegung für den PC lautet wie folgt: {| class="wikitable" |- ! RJ12 !! Sub-D |- | 4 Rx || 3 |- | 5 Tx || 2 |- | 7 GND || 5 |} Achtung: Die Zählweise beim RJ12-Stecker beginnt bei 2. Aufgrund der mäßigen Beschreibung im Datenblatt kann es sein, dass die Belegung gespiegelt ist (werde ich noch prüfen) Das Auslesen findet "aktiv" statt, d. h. man muss Werte abfragen - der Regler sendet von sich aus nichts. Zum Abfragen der Temperaturen muss man 0xCE <addr> 0x00 0x00 <checksum> senden. Für die Checksum muss man alle gesendeten Bytes ver-XOR-en, für die Temperaturen also einfach 0xCE ^ addr. {| class="wikitable" |- ! Adresse !! Anschluss |- | 0xFA || B8 |- | 0x32 || B5 |- | 0x34 || B4 ? |- | 0xF8 || B3 ? |- | 0xFC || B7 ? |- | 0x38 || B2 |- | 0x3C || B1 |} [http://de.fernwaerme.danfoss.com/xxTypex/17613_MNU17407525_SIT21.html Produktseite bei Danfoss] === ECA 86 === [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt [http://de.fernwaerme.danfoss.com/Product/087B1158_MNU17407526.html Produktseite bei Danfoss] === ECA 60 === [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEProm 93C66A (512x8 bit) gespeichert. [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407525.html Produktseite bei Danfoss] == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung !! Häufigkeit |- | AF || 04 || Innentemperatur (ECA 60) || 125/h |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || -- |- | AF || 09 || Abfrage Tagesprogramm || 63/h |- | AF || 11 || Zeit setzen || -- |- | EF || 60 || Temperaturfühler ECA 86 || 125/h |- | F0 || 01 || Außentemperatur || 125/h |- | F0 || 02 || Aktuelle Zeit || 125/h |- | FA || 05 || Solltemperatur am ECL 300 setzen || -- |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) || -- |- | FA || 09 || Tagesprogramm (Antwort auf AF06) || 63/h |- | FE || 62 || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine Stunde, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. Die Positionsangaben b[x] beziehen sich auf den 0-basierenden Index im Paket, die Angabe "das x-te Byte" auf die 1-basierende Position. Das Byte zu Beginn eines Pakets ist also b[0] und wird mit "1. Byte" bezeichnet. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 Temperatur </pre> Im 4. Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im dritten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[3] + b[2]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger (siehe Diagramm). === AF05/FA05/FF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? !!!!!!!0 !!!!!!!0 ?0000!!! Soltmp. Abw.tmp. Modus </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das dritte Byte (b[2]) bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. ==== Solltemperatur ==== Im 5. Byte befindet sich die Solltemperatur um ein Bit verschoben (b[3] >> 1). ==== Abweichende Temperatur ==== Im 6. bzw. 7. Byte ist die Abweichung zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gültig ist. Im Modus "Entspannen" wird die Abweichung in b[5] gespeichert, bei "Abwesenheit" in b[6]. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Um echte 8-Bit-Integer verwenden zu können, werden im Code die fehlenden Bits ersetzt: <pre> if(type == ECL_DIFF_RELAX) { ecl_data.tmp_diff = buff[5] >> 1; if(ecl_data.tmp_diff & 0x20) { ecl_data.tmp_diff |= 0xC0; } } else if(type == ECL_DIFF_AWAY) { ecl_data.tmp_diff = buff[6] >> 1; if(ecl_data.tmp_diff & 0x40) { ecl_data.tmp_diff |= 0x80; } } </pre> Das Setzen einer Abweichungen ist etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern. ==== Betriebsart ==== Das letzte (8.) Byte zeigt an, in welcher Betriebsart sich der Regler befindet. {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Handbetrieb |- | 001 || 1 || Zeitgesteuerter Betrieb |- | 010 || 2 || Konstante Komforttemperatur |- | 011 || 3 || Konstante reduzierte Temperatur |- | 100 || 4 || Standby |} Die restlichen möglichen Stati sind mir nicht bekannt. === AF06/FA06 (Bestätigung Solltemperatur) === Dieses Paket dient anscheinend der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (FA06 folgt auf AF05 bw. AF06 folgt auf FA05) direkt nach einem **05-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden. === AF09/FA09 (Tagesprogramm) === Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen. Um diese Daten zu erhalten, muss es folgendes auf den Bus legen: <pre> AF09 00000010 00000000 00000000 00000000 00000000 00000000 00000!!! 00000000 00000000 00000000 00000000 00000000 Tag </pre> Die untersten 3 Bit des dritten Byte entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6. Der ECL300 antwortet dann wie folgt: <pre> FA09 00001111 11111111 11111111 11111111 11110000 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ^ 23:30 00:00 ^ </pre> Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet. In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr. === AF11/F002 (Zeit setzen/Aktuelle Zeit) === <pre> F002 *** TODO *** 0!!!!!!! 0!!!!!!! 00!!!!!!! 00!!!!!! !!!!!!!! !!!!!!!! Sekunde Minute Stunde Tag Jahr WTagMona </pre> Die Uhrzeit ist einfacher aufgebaut, als man Denkt. In den Bytes folgen aufeinander die Sekunde (b[2]), Minute und Stunde des aktuellen Tags. Der aktuelle Tag wird im 6. Byte gespeichert, das 8. Byte enthält im höherwertigen Nibble den aktuellen Wochentag (TODO: welcher ist nochmal der erste?) und im niederwertigen den aktuellen Monat (1-12). Das Jahr (b[6]) ist relativ zum Jahr 1900 notiert. Um den "korrekten" Wert zu erhalten, muss man zu dem empfangenen Byte einfach 1900 addieren. === EF60 (Temperatursensoren ECA86) === <pre> EF60 10000001 00011110 01101000 00001001 00100011 00000000 EF60 01110101 00011111 00000000 01100000 01000101 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! 00000000 Temperatur Bx/x Temperatur Bx/x Index </pre> Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt. Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes nach der Adresse, der zweite in den beiden darauf folgenden. Das 7. Byte gibt an, um welche Werte es sich handelt. === F001 (Außentemperatur) === <pre> F001 *** TODO *** !!!!!!!! ?!!!!!!! ???????? !!!!!!!! ???????? ???????? Temperatur Modus </pre> In den beiden Bytes nach der Adresse steht - im gleichen Schema wie die Innentemperatur - Kodierte Außentemperatur. Im 6. Byte stehen die Modi für die beiden Heizkreise. Das die oberen 4 Bit repräsentieren hier den Brauchwasserkreis, die unteren 4 den Heizkreis. {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Reduzierte Temperatur |- | 01 || 1 || Optimierte Aufheizphase |- | 10 || 2 || Komforttemperatur |- | 11 || 3 || Optimierte Absenkphase |} Selbst miterlebt habe ich nur Modus 0 und 2, die anderen beiden entstanden aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet. Was mit den restlichen 12 möglichen Stati ist, weiß ich nicht. === FE62 (Setzen Relais an ECA 86) === == Prüfsumme == Wie bereits im [http://hobbyelektronik.org/b/?p=415 Blog] bemängelt ist die Prüfsumme nicht allzu solide. Sie wird berechnet, indem alle Bytes des Pakets exklusive der vorletzten beiden miteinander addiert (!) werden und mit 0xFF verundet werden. Diese "Prüfsumme" entspricht dem vorletzten Byte des Pakets, wobei es manchmal vorkommt, dass das MSB gekippt ist (näherer Grund ist noch unbekannt). Das letzte Paket im Byte ist immer 0x0D, was zur Synchronisierung verwendet werden kann. == Was fehlt noch? == === Störung === Seitdem ich die Daten erfasse hatte ich leider/zum Glück noch keine Störung der Anlage. Ich könnte sie zwar am Alarmmodul künstlich erzeugen, war bisher aber noch nicht mutig/dumm genug. Laut Installateur werden Störungen auf dem ECA60 angezeigt, deshalb liegt sehr nahe, dass diese auch über den Bus übertragen werden. === Aktives Auslesen === Dass das aktive Auslesen von Parametern funktioniert, zeigt das ECA 60 mit dem aktuellen Tagesprogramm. Geht das auch mit anderen Werten? = Download = Folgt :-) 2b0f5893e8080cb89316004e75d3f339096392bb 642 640 2011-05-04T20:45:04Z Chris 2 Die Firmware ist da! wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: == Busteilnehmer == {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} === ECL 300 === [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Das/Der ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. Auf der Vorderseite befindet sich eine Diagnoseschnittstelle, die als RS232 mit 1200 Baud, 8 Bit, Odd Parity und 2 Stoppbits spricht. Der Stecker ist ein RJ12 (6P6C), die Anschlussbelegung für den PC lautet wie folgt: {| class="wikitable" |- ! RJ12 !! Sub-D |- | 4 Rx || 3 |- | 5 Tx || 2 |- | 7 GND || 5 |} Achtung: Die Zählweise beim RJ12-Stecker beginnt bei 2. Aufgrund der mäßigen Beschreibung im Datenblatt kann es sein, dass die Belegung gespiegelt ist (werde ich noch prüfen) Das Auslesen findet "aktiv" statt, d. h. man muss Werte abfragen - der Regler sendet von sich aus nichts. Zum Abfragen der Temperaturen muss man 0xCE <addr> 0x00 0x00 <checksum> senden. Für die Checksum muss man alle gesendeten Bytes ver-XOR-en, für die Temperaturen also einfach 0xCE ^ addr. {| class="wikitable" |- ! Adresse !! Anschluss |- | 0xFA || B8 |- | 0x32 || B5 |- | 0x34 || B4 ? |- | 0xF8 || B3 ? |- | 0xFC || B7 ? |- | 0x38 || B2 |- | 0x3C || B1 |} [http://de.fernwaerme.danfoss.com/xxTypex/17613_MNU17407525_SIT21.html Produktseite bei Danfoss] === ECA 86 === [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt [http://de.fernwaerme.danfoss.com/Product/087B1158_MNU17407526.html Produktseite bei Danfoss] === ECA 60 === [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEProm 93C66A (512x8 bit) gespeichert. [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407525.html Produktseite bei Danfoss] == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung !! Häufigkeit |- | AF || 04 || Innentemperatur (ECA 60) || 125/h |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || -- |- | AF || 09 || Abfrage Tagesprogramm || 63/h |- | AF || 11 || Zeit setzen || -- |- | EF || 60 || Temperaturfühler ECA 86 || 125/h |- | F0 || 01 || Außentemperatur || 125/h |- | F0 || 02 || Aktuelle Zeit || 125/h |- | FA || 05 || Solltemperatur am ECL 300 setzen || -- |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) || -- |- | FA || 09 || Tagesprogramm (Antwort auf AF06) || 63/h |- | FE || 62 || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine Stunde, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. Die Positionsangaben b[x] beziehen sich auf den 0-basierenden Index im Paket, die Angabe "das x-te Byte" auf die 1-basierende Position. Das Byte zu Beginn eines Pakets ist also b[0] und wird mit "1. Byte" bezeichnet. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 Temperatur </pre> Im 4. Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im dritten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[3] + b[2]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger (siehe Diagramm). === AF05/FA05/FF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? !!!!!!!0 !!!!!!!0 ?0000!!! Soltmp. Abw.tmp. Modus </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das dritte Byte (b[2]) bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. ==== Solltemperatur ==== Im 5. Byte befindet sich die Solltemperatur um ein Bit verschoben (b[3] >> 1). ==== Abweichende Temperatur ==== Im 6. bzw. 7. Byte ist die Abweichung zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gültig ist. Im Modus "Entspannen" wird die Abweichung in b[5] gespeichert, bei "Abwesenheit" in b[6]. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Um echte 8-Bit-Integer verwenden zu können, werden im Code die fehlenden Bits ersetzt: <pre> if(type == ECL_DIFF_RELAX) { ecl_data.tmp_diff = buff[5] >> 1; if(ecl_data.tmp_diff & 0x20) { ecl_data.tmp_diff |= 0xC0; } } else if(type == ECL_DIFF_AWAY) { ecl_data.tmp_diff = buff[6] >> 1; if(ecl_data.tmp_diff & 0x40) { ecl_data.tmp_diff |= 0x80; } } </pre> Das Setzen einer Abweichungen ist etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern. ==== Betriebsart ==== Das letzte (8.) Byte zeigt an, in welcher Betriebsart sich der Regler befindet. {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Handbetrieb |- | 001 || 1 || Zeitgesteuerter Betrieb |- | 010 || 2 || Konstante Komforttemperatur |- | 011 || 3 || Konstante reduzierte Temperatur |- | 100 || 4 || Standby |} Die restlichen möglichen Stati sind mir nicht bekannt. === AF06/FA06 (Bestätigung Solltemperatur) === Dieses Paket dient anscheinend der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (FA06 folgt auf AF05 bw. AF06 folgt auf FA05) direkt nach einem **05-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden. === AF09/FA09 (Tagesprogramm) === Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen. Um diese Daten zu erhalten, muss es folgendes auf den Bus legen: <pre> AF09 00000010 00000000 00000000 00000000 00000000 00000000 00000!!! 00000000 00000000 00000000 00000000 00000000 Tag </pre> Die untersten 3 Bit des dritten Byte entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6. Der ECL300 antwortet dann wie folgt: <pre> FA09 00001111 11111111 11111111 11111111 11110000 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ^ 23:30 00:00 ^ </pre> Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet. In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr. === AF11/F002 (Zeit setzen/Aktuelle Zeit) === <pre> F002 *** TODO *** 0!!!!!!! 0!!!!!!! 00!!!!!!! 00!!!!!! !!!!!!!! !!!!!!!! Sekunde Minute Stunde Tag Jahr WTagMona </pre> Die Uhrzeit ist einfacher aufgebaut, als man Denkt. In den Bytes folgen aufeinander die Sekunde (b[2]), Minute und Stunde des aktuellen Tags. Der aktuelle Tag wird im 6. Byte gespeichert, das 8. Byte enthält im höherwertigen Nibble den aktuellen Wochentag (TODO: welcher ist nochmal der erste?) und im niederwertigen den aktuellen Monat (1-12). Das Jahr (b[6]) ist relativ zum Jahr 1900 notiert. Um den "korrekten" Wert zu erhalten, muss man zu dem empfangenen Byte einfach 1900 addieren. === EF60 (Temperatursensoren ECA86) === <pre> EF60 10000001 00011110 01101000 00001001 00100011 00000000 EF60 01110101 00011111 00000000 01100000 01000101 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! 00000000 Temperatur Bx/x Temperatur Bx/x Index </pre> Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt. Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes nach der Adresse, der zweite in den beiden darauf folgenden. Das 7. Byte gibt an, um welche Werte es sich handelt. === F001 (Außentemperatur) === <pre> F001 *** TODO *** !!!!!!!! ?!!!!!!! ???????? !!!!!!!! ???????? ???????? Temperatur Modus </pre> In den beiden Bytes nach der Adresse steht - im gleichen Schema wie die Innentemperatur - Kodierte Außentemperatur. Im 6. Byte stehen die Modi für die beiden Heizkreise. Das die oberen 4 Bit repräsentieren hier den Brauchwasserkreis, die unteren 4 den Heizkreis. {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Reduzierte Temperatur |- | 01 || 1 || Optimierte Aufheizphase |- | 10 || 2 || Komforttemperatur |- | 11 || 3 || Optimierte Absenkphase |} Selbst miterlebt habe ich nur Modus 0 und 2, die anderen beiden entstanden aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet. Was mit den restlichen 12 möglichen Stati ist, weiß ich nicht. === FE62 (Setzen Relais an ECA 86) === == Prüfsumme == Wie bereits im [http://hobbyelektronik.org/b/?p=415 Blog] bemängelt ist die Prüfsumme nicht allzu solide. Sie wird berechnet, indem alle Bytes des Pakets exklusive der vorletzten beiden miteinander addiert (!) werden und mit 0xFF verundet werden. Diese "Prüfsumme" entspricht dem vorletzten Byte des Pakets, wobei es manchmal vorkommt, dass das MSB gekippt ist (näherer Grund ist noch unbekannt). Das letzte Paket im Byte ist immer 0x0D, was zur Synchronisierung verwendet werden kann. == Was fehlt noch? == === Störung === Seitdem ich die Daten erfasse hatte ich leider/zum Glück noch keine Störung der Anlage. Ich könnte sie zwar am Alarmmodul künstlich erzeugen, war bisher aber noch nicht mutig/dumm genug. Laut Installateur werden Störungen auf dem ECA60 angezeigt, deshalb liegt sehr nahe, dass diese auch über den Bus übertragen werden. === Aktives Auslesen === Dass das aktive Auslesen von Parametern funktioniert, zeigt das ECA 60 mit dem aktuellen Tagesprogramm. Geht das auch mit anderen Werten? = Firmware = {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = CB | FuseL = FD }} Die Firmware für AVRs (oder besser gesagt C-Code) belegt einen Pin- (INT0) und einen Timer-Interrupt (TIMER0), mit denen das Signal vom ECL-Bus gesampelt wird. Die ISRs hierfür können in jeder beliebigen C-Datei stehen. die aufgerufenen Funktionen werden vom Compiler inline eingefügt. Damit das ohne zusätzlichen Speicherplatz funktioniert, musste ich (da ich es zugegebenermaßen nicht besser weiß), den Code fürs Sampeln in die H-Datei des Decoders einfügen. (Wer eine bessere/richtige Methode kennt, ich freue mich über Feedback!) In der Main-Schleife des Programms muss zusätzlich ecl_decode() aufgerufen werden, welche das zuletzt empfangene Paket auswertet und in die Variable ecl_data schreibt. Die Funktion sollte alle 8-12ms aufgerufen werden, damit kein Paket verpasst wird. Hier könnte noch etwas Optimierungsbedarf bestehen. Die Praxis wird zeigen, wie (un)günstig die aktuelle Einlesemethode ist. Um flexibel zu bleiben, verwendet der Code einige Präprozessoranweisungen, über die die einzulesenden Daten sowie Speicherbelegung beeinflusst werden können. Über die Konfiguration kann auch das Debugging konfiguriert werden. Die Beschaltung ist - wie oben weiter oben zu lesen - sehr einfach. Der ECL-Bus wird über einen Optokoppler galvanisch getrennt. Der Kollektor des Optos wird über einen Pull-Up nach oben gezogen (der AVR-interne dürfte hierfür reichen, momentan wird ein externer vorausgesetzt) und das Signal an PD2 (INT0) weitergegeben. In der Standardkonfiguration lässt der Code nur eine an PD6/PD7 gegen Masse angeschlossene Duo-LED (Grün an PD6, Rot an PD7) je nach empfangenem Paket/Status kurz aufleuchten. Konkrete Daten erhält man, wenn man das rudimentäre Debugging aktiviert und am UART bei 19200 Baud 8N1 lauscht. = Download = [[Datei:ECLBus.zip]] Version 0.1, AVR-Studio-Projekt [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] 3540044558ed982f836fc99a097c9f265a69b112 MediaWiki:Sidebar 8 8 619 64 2011-04-11T15:12:07Z Qsysopr 1 wikitext text/x-wiki * navigation ** mainpage|mainpage ** portal-url|portal ** currentevents-url|currentevents ** recentchanges-url|recentchanges ** randompage-url|randompage ** Spezial:Alle_Seiten|'''Alle Seiten''' * Bereiche ** Category:Elektronik|Elektronik (ohne µC) ** Category:AVR|AVR ** Category:PC|am PC ** Category:Software|Software (PC) ** Category:LCD|LCDs ** Category:Maschinen|Maschinen ** Category:Sonstiges|Sonstiges ** Category:Murks|Murks 1199a16aef4f025a2355df530f6c2276c5c61ac2 620 619 2011-04-11T15:12:23Z Qsysopr 1 wikitext text/x-wiki * navigation ** mainpage|mainpage ** portal-url|portal ** currentevents-url|currentevents ** recentchanges-url|recentchanges ** randompage-url|randompage ** Spezial:Alle_Seiten|Alle Seiten * Bereiche ** Category:Elektronik|Elektronik (ohne µC) ** Category:AVR|AVR ** Category:PC|am PC ** Category:Software|Software (PC) ** Category:LCD|LCDs ** Category:Maschinen|Maschinen ** Category:Sonstiges|Sonstiges ** Category:Murks|Murks 3770c6ec7c55b9c198fb623af19645aa47c4acc4 Datei:ECA60 Temperatur.PNG 6 233 622 2011-04-12T17:37:46Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Minidoper.png 6 234 624 2011-04-13T13:36:52Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Minidoper.zip 6 235 625 2011-04-13T13:42:09Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 AVR-Doper 0 44 626 580 2011-04-13T13:44:07Z Chris 2 Minidoper hinzugefügt wikitext text/x-wiki {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = C9 | FuseL = 9F }} Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Die Firmware wurde nicht verändert und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download des optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] =AVR-Doper unter Windows 7= Nachdem Windows XP schon etwas betagt ist und Vista eher ein flop war, steht man früher oder später an dem Punkt, Windows 7 zu verwenden. Zwar lassen sich die Vista-Treiber des AVR-Dopers unter Windows 7 installieren, AVR-Studio kann allerdings keine Verbindung zum Doper herstellen. Die Jungs von recursion.jp haben einen Treiber geschrieben, der sowohl unter Win7 x86 und Win7 x64 funktioniert: [http://www.recursion.jp/avrcdc/lowbulk.html http://www.recursion.jp/avrcdc/lowbulk.html] -> "avrcdc_inf.zip" Es kann sein, dass der Treiber manuell signiert werden muss (was bei meiner x86-Installation nicht erforderlich war). Nähere Informationen dazu (und auch der ursprüngliche Hinweis auf den Treiber) befinden sich im [http://forums.obdev.at/viewtopic.php?f=8&t=3591&p=12721#p12721 Forum von Objective Development] =Patch AVR-Studio= Wer den AVR-Doper direkt in Atmels AVR-Studio als STK500 benutzt, erhält bei jedem Herstellen der Verbindung eine nervige Fehlermeldung bezüglich der Firmware-Version. Ein kleiner Registry-Eintrag unterdrückt die Meldung: Unter HKEY_LOCAL_MACHINE\SOFTWARE\Atmel\AVRTools\STK500 muss VersionMajor auf 0x00000002 (2) und VersionMinor auf 0x00000004 (4) geändert werden. Für die, die den Registrierung-Editor nicht bedienen können oder möchten, gibt es eine passende Reg-Datei: [[Datei:Avr-doper-registry.zip]] Wer sich die Tortur angetan hat und den Doper per virtuellem COM-Port an Vista/Win7 x64 zum laufen gebracht hat, muss die Änderung im Pfad HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Atmel\AVRTools\STK500 vornehmen. Also entweder in der .reg-Datei ändern oder manuell dort hin navigieren und bearbeiten. =Minidoper= [[Datei:Minidoper.png|200px|thumb|Mini-Version von Jan]] Jan Räker hat sich die Mühe gemacht und den Doper nochmal ein gutes Stück verkleinert und mir zur Veröffentlichung (unter [http://creativecommons.org/licenses/by-sa/3.0/ by-sa]) bereitgestellt: [[Datei:Minidoper.zip]] [[Category:AVR]] [[Category:USB]] [[Category:PC]] 09b24eb6be6d37bec07549b248950ecad704bb9b Datei:Eca60.jpg 6 236 632 2011-04-24T09:57:01Z Chris 2 Raumleitgerät ECA 60 von Danfoss wikitext text/x-wiki Raumleitgerät ECA 60 von Danfoss 26f1524b8165ad0d4b55a739d7da9d93d90d103f Datei:Ecl300.jpg 6 237 633 2011-04-24T09:57:20Z Chris 2 Regler ECL 300 von Danfoss wikitext text/x-wiki Regler ECL 300 von Danfoss df2d374f3a24a95d27c42846947ffedc747d0ce6 Datei:Eca86.jpg 6 238 634 2011-04-24T09:58:25Z Chris 2 Temperaturüberwachungs- und Alarmmeldemodul ECA 86 von Danfoss wikitext text/x-wiki Temperaturüberwachungs- und Alarmmeldemodul ECA 86 von Danfoss de009aa64efbb6263f164bcba29651d287ee2344 Datei:ECLBus.zip 6 239 641 2011-05-04T20:16:56Z Chris 2 Decoder für den Danfoss-ECL-Bus, Atmega 8 mit 12MHz. wikitext text/x-wiki Decoder für den Danfoss-ECL-Bus, Atmega 8 mit 12MHz. 8b91e033b088dbd7d020f002c3394e9bda6aaf69 Energieerfassung 0 168 643 569 2011-05-04T20:45:46Z Chris 2 Kategorie hinzugefügt wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== [[Datei:Nrg hauptzaehler.jpg|thumb|Stromzähler mit aufgesetzter Erfassungseinheit]] Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[:wpde:Ferraris-Zähler|Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. [[Datei:Bananen Frucht.jpg|thumb|Eine Banane, eisenreich und sehr bekömmlich (cc:by-sa Darkone)]] Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. <gallery> Datei:Nrg zaehler umlauf.png|Ein Umlauf, wie er direkt am Fototransistor gemessen wird Datei:Nrg zaehler rauschen.png|"Grundrauschen" der rotierenden Scheibe (ohne DC-Offset) </gallery> Die Leistungsaufnahme lässt sich anhand der Umlaufzeit wie folgt berechnen: [[Datei:Nrg formel leistung.png]] Setzt man die im Screenshot ermittelten 42.6 Sekunden ein, erhält man eine Leistung von ~1127 Watt. Da die Leistung mit der Zeit exponentiell abnimmt, ist bei hohen Leistungsaufnahmen eine relativ hohe Auflösung der Zeit erforderlich. Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: <gallery> Datei:Nrg zaehler auswert.png|Auswerteschaltung Datei:Nrg zaehler pass.png|Zählersignal vor (blau) und nach (gelb) dem Filter </gallery> Links wird der Fototransistor in Sperrrichtung angeschlossen. Der 1µF-Elko und der nachfolgende 100k-Widerstand stellt einen Hochpass mit nicht näher definierter Grenzfrequenz (WolframAlpha sagt [http://www.wolframalpha.com/input/?i=1%2F%282*Pi*100kOhms*1%C2%B5F%29 1.592Hz]) dar. Die Frequenz ist ist im Hinblick auf [[:wpde:Hochpass:Ordnung]], Bauteiletoleranzen und der Zielfrequenz vermutlich nicht einmal ein Richtwert. Der folgende Hochpass hat eine Grenzfrequenz von ca. 16Hz. Hier gilt das gleiche Vertrauen wie in den Tiefpass. Aber alles kein Problem: Die Werte sind weitestgehend unkritisch. Es sind Umläufe im Millihertz-Bereich (also Umlaufdauern in der Größenordnung Sekunden bis Minuten) zu erwarten. Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. [[Datei:Nrg tarifzaehler.jpg|thumb|Tarifzähler, rechts das Fähnchen zum Anzeigen des Tarifs]] Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. [[Datei:Nrg_relais_freigabe.jpg|thumb|Relais für die Stromfreigabe, mit LED]] Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. '''Update 10.10.2010:''' Weasel (IRC) ist beim Anblick der Kennlinie der Temperatursensoren in der Anleitung des Vitosolic 200 blitzschnell darauf gekommen, dass es sich um PT500-Elemente handeln müssen, die jedoch nur für sehr teuer Geld erhältlich sind. Mein anfänglicher Scherz vonwegen 2 PT1000 parallel ergibt PT500 hat sich als gar nicht so dumm erwiesen: Idealerweise sind die Widerstände der Sensoren bei gleicher Temperatur ebenfalls gleich, Durch Parallelschaltung zweier PT1000 kann man sie problemlos an der PT1000 betreiben! Da ich sonst nichts mit meinen 9 Sensoren anzufangen wusste, fristen jetzt 8 dieser als 4 Fühler im Keller ihr dasein: Zwei erfassen die Ein- und Auslasstemperatur an der "Primärseite" der Wärmepumpe, einer sitzt im Warmwasserspeicher in oberster Schicht und der 4. misst (da mir noch nichts besseres einfiel) die Raumtemperatur im Heizkeller, die mangels Isolierung der Rohre deutlich zu hoch ist. '''Update-Ende''' === Was kommt rein? === Auf der Unterseite [[Energieerfassung/Solarleistung]] habe ich beschrieben, wie man anhand einiger Parameter die Leistung der Solaranlage berechnen kann ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. <gallery> Datei:Nrg shield.jpg|Shield des Großhirns Datei:Nrg grosshirn.jpg|Hirn von oben </gallery> ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. <gallery> Datei:Nrg lcd 1.jpg|Home-Screen mit Datum und Uhrzeit Datei:Nrg lcd 2.jpg|Aktueller Stromverbrauch Datei:Nrg lcd 3.jpg|Solardaten: Kollektortemperatur, Pumpenlast und Speichertemp. Datei:Nrg lcd 4.jpg|Debuginfos, Timeouts des TCP/IP-Stacks und Refresh des NTP-Clients </gallery> ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== [[Datei:Nrg json.png|thumb|Exemplarischer JSON-Datensatz]] Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= Aktuelle Firmware, EAGLE-Dateien des Shields (ohne V-Bus-Pegelwandler): [[Datei:Energieerfassung Firmware.zip]] =Nerviges/Todo= *Die interne Uhr hat eine sehr hohe Gangabweichung. Macht sich trotz kurzer NTP-Refresh-Intervallen bemerkbar *Der Speicher für die historischen Daten ist sehr klein. Bei Ausfall der Internetverbindung/Server/Cronjob gibt es zu schnell Lücken *Erfassung des Wasserzählers *Erfassung Außentemperatur =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Pads der LEDs zu groß und Widerstände gegen GND geschaltet) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann *[http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller *Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] 6f9bae427f4c8fba6bcd7164f0f266ba89627c5c Energieerfassung/Solarleistung 0 205 644 568 2011-05-04T20:46:28Z Chris 2 Kategorie hinzugefügt wikitext text/x-wiki [[Datei:Solar schem.png|thumb]] Die Erfassung der Betriebsdaten ist schön und gut. Solange man sie nicht richtig auswerten kann passiert eigentlich nicht viel, außer dass die Datenbank immer größer wird. Mein mittelfristiges Ziel der Energieerfassung ist zu ermitteln, was reingeht und was rauskommt. [[Energieerfassung#W.C3.A4rme_Extrem|Letzteres]] habe ich ja (zumindest vorerst) zurückgestellt. Ersteres kann ich mittlerweile zumindest teilweise machen. Die Solaranlage basiert drauf, dass die in den Kollektoren aufgefangene Energie in thermische umgewandelt wird um sie dann im Wärmetauscher dem Heizkreislauf zuzuführen. Im Groben sieht das dann so aus, wie rechts im Bild zu sehen ist. Aber wie viel Energie ist es denn? Die Physik bietet hierfür die [[wpde:Spezifische Wärmekapazität|spezifische Wärmekapazität]] als Lösung an: [[Datei:Solar spezwk.png]] ΔQ ist die Energie, die der Materie (also dem Wärmeträger) zugefügt oder entnommen wurde, c die spezifische Wärmekapazität und ΔT die Temperaturdifferenz beim zufügen oder entnehmen der Energie. Man benötigt also nur drei Parameter um herauszufinden, wie viel Energie dem Heizkreislauf zugefügt wurde. In unserer Solaranlage wird das Wärmeträger "Tyfocor® G-LS" verwendet. Im Datenblatt dazu (Veröffentlichung an dieser Stelle muss ich noch klären) ist die spezifische Wärmekapazität als lineare Kurve angegeben. Über die Punktsteigungsform lässt sie sich mit folgender Formel ermitteln: [[Datei:Solar wkap.png]] Fehlt nur noch die Masse der Flüssigkeit. Das wird schon ein bisschen kniffeliger. Laut unserem Heizungsbauer sind - wenn ich mich richtig erinnere - 6 Liter der Brühe in der Anlage. Diese Information hilft aber recht wenig, da man ja nur interessiert, was im Wärmetauscher vor sich geht. Die Angabe der zum System zugeführten Energie für die meisten ein eher nichtssagender Wert. Ich könnte jedem auf der Straße erzählen, dass in meinem Puffer 80 Joule gespeichert sind ohne dass sie merken, dass man damit nicht einmal einen kleinen Eiswürfel schmelzen könnte. Mit Leistung kann aber jeder etwas anfangen. Mit einem Wasserkocher mit 2000 Watt dauert es vielleicht drei Minuten, bis ein Liter Wasser kocht. Damit kann jeder etwas anfangen. Hinter dieser Angabe steckt nichts anderes als die Energie - 2000W * 180s sind 360000Ws. Wattsekunden entsprechen gleichzeitig Joule. Viola - Energie! Eines muss ich vorweg sagen: Den letzten Abschnitt habe ich ein bisschen hingedreht. Tatsächlich kommt bei der Berechnung eine Leistung in Watt heraus, obwohl bei der oben genannten Formel eine Energieänderung das Ergebnis ist. Der Hintergrund hierfür ist, dass die Flüssigkeit im System nicht steht, sondern sich bewegt. Zunächst gilt es aber herauszufinden, wie viel Masse die bewegte Flüssigkeit hat. Die Dichte ist ebenso im Datenblatt vermerkt. Leider handelt es sich hier nicht um eine lineare Abhängigkeit zur Temperatur. Da sich die unlinearität allerdings in Grenzen hält (und ich ehrlich gesagt keine Lust auf eine Ausgleichsrechnung hatte), wird die Dichte mit folgender Formel angenähert: [[Datei:Solar dichte.png]] Über die Dichte kann man in Verbindung mit dem Volumen die Masse der Flüssigkeit berechnen, [[Datei:Solar masse.png]] wo wir schon beim nächsten Problem wären: Wie viel Volumen ist im Wärmetauscher oder besser - wie viel geht da durch? Glücklicherweise ist im Primärkreis der Solaranlage ein Strömungsmesser angebracht, der den Durchfluss in Liter pro Minute angibt. Mit einer kleinen Umrechnung kommt man auf die [[wpde:Si-Einheit|Si-Einheit]] m³/s, womit man wieder schön rechnen kann. Leider kann man den Durchfluss nicht direkt aus der Pumpenleistung berechnen, da damit mehrere Faktoren (z. B. thermische Konvektion) zusammenhängen. Um zumindest einen Richtwert zu erhalten, habe ich die Werte des Durchflusses für verschiedene Pumpenleistungen notiert. Der Durchfluss wird momentan über eine Lookup-Table ermittelt. Sobald ich mehrere Werte habe, werden diese natürlich mit in die Formel gepackt. Zusammengesetzt ergibt sich aus den einzelnen Formeln folgendes Gebilde: [[Datei:Solar formel.png]] Theoretisch bräuchte man bei der Bestimmung der Dichte und spezifischen Wärmekapazität unendlich viele Werte, da die Temperatur des Mediums im Wärmetauscher abnimmt. Da ich hier jedoch nicht mit Integralen um mich werfen will, habe ich den Wärmetauscher als unendlich klein definiert und den Mittelwert der Ein- und Ausgangstemperatur verwendet. Das ist zwar nicht zwangsläufig korrekt, sollte aber eine (für diese Anwendung) brauchbare Annäherung an die Wirklichkeit sein (Mann, hört sich das wissenschaftlich an...). Mit der Einheitenkontrolle wird geprüft, dass die Formel keine groben Schnitzer hat: [[Datei:Solar feinheiten.png]] Alle Werte kürzen sich - ich bin zufrieden! Nimmt man die Zeit (t) auf die linke Seite, ergibt sich die Leistung in kW - was will man mehr? Fehlt nur noch die Probe auf Exempel - sind reale Werte von der Solaranlage plausibel? Eingesetzt, ausgerechnet: ja! Eine Tabelle muss ich noch erstellen und hochladen, aber es sieht ziemlich gut aus. [[Kategorie:Energieerfassung]] 43bae8e1f57485834a69bf50e34eeec0276328ce VBus-Decoder 0 120 645 558 2011-05-04T20:47:07Z Chris 2 Kategorie entfernt und hinzugefügt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die zwar Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <pre> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </pre> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <pre> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </pre> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] 80aaac176a97138ffb58f82cf70fbcb5160926b5 659 645 2011-06-12T21:39:01Z Chris 2 /* Hardwareschnittstelle */ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <pre> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </pre> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <pre> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </pre> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] 43641c59c25bfd727ffb4c4d6ade410261ce7616 Kategorie:Energieerfassung 14 240 646 2011-05-04T20:48:13Z Chris 2 Kategorieseite angelegt wikitext text/x-wiki Diese Kategorie beinhaltet alle Wiki-Artikel, die sich mit [[Benutzer:Chris|Chris']] Energieerfassung befassen: 5eac1d6c2cb4f01d4743e7d88d795bcdc0d01c98 Hauptseite 0 1 647 610 2011-05-04T20:49:04Z Chris 2 /* Neues */ wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *04.05.2011 [[ECL-Bus-Decoder]] *19.03.2011 [[Physik-Formelsammlung]] *15.01.2011 [[Belichtungsgeraet]] *09.01.2010 [[ASCII-Tabelle]] *09.12.2010 [[Energieerfassung/Solarleistung]] *10.10.2010 [[Kameratimer]] =Updates= *19.03.2010 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll 1b8ddbda86c7595b85f790c69d684f6f35071a19 658 647 2011-06-11T23:01:49Z Robert 3 /* Neues */ wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *12.06.2011 [[Maschinenleuchte]] *04.05.2011 [[ECL-Bus-Decoder]] *19.03.2011 [[Physik-Formelsammlung]] *15.01.2011 [[Belichtungsgeraet]] *09.01.2010 [[ASCII-Tabelle]] *09.12.2010 [[Energieerfassung/Solarleistung]] *10.10.2010 [[Kameratimer]] =Updates= *19.03.2010 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll 36c11ef9a573cce40429990cc73d0b52d86aad50 677 658 2011-09-13T22:09:16Z Chris 2 Neues aktualisiert wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] *12.06.2011 [[Maschinenleuchte]] *04.05.2011 [[ECL-Bus-Decoder]] *19.03.2011 [[Physik-Formelsammlung]] *15.01.2011 [[Belichtungsgeraet]] *09.01.2010 [[ASCII-Tabelle]] =Updates= *19.03.2010 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll e74a7b1041d985e6f6e16149da9afd72fda8526c Testseite 0 2 648 435 2011-05-10T21:30:40Z Chris 2 Test mit Geshi wikitext text/x-wiki {{Infobox AVR | Typ = AtMega Schießmichtot | Takt = 42 | FuseH = 0xFF | FuseL = 0xFF }} Testseite, für interne Verwendung. <syntaxhighlight lang="php"> <?php ladida(); $var = fopen("foobar"); ?> </syntaxhighlight> [[Datei:Xkcd.png]] [[Datei:Xkcd.png|thumb]] [[Category:Elektronik]] 9b5850ea5adee7226b689ac2a4d97f0482dc33b3 660 648 2011-06-22T21:22:55Z Chris 2 Mal sehen, ob MathJax funktioniert... wikitext text/x-wiki {{Infobox AVR | Typ = AtMega Schießmichtot | Takt = 42 | FuseH = 0xFF | FuseL = 0xFF }} <math>\int_{0}^{42} \frac{23}{42}x^{2} dx</math> Testseite, für interne Verwendung. <syntaxhighlight lang="php"> <?php ladida(); $var = fopen("foobar"); ?> </syntaxhighlight> [[Datei:Xkcd.png]] [[Datei:Xkcd.png|thumb]] [[Category:Elektronik]] 42a78752b504c681e3c9767eb90df1642c217623 661 660 2011-07-08T22:09:15Z Chris 2 Jetzt sollte die Formel super aussehen :) wikitext text/x-wiki {{Infobox AVR | Typ = AtMega Schießmichtot | Takt = 42 | FuseH = 0xFF | FuseL = 0xFF }} :<math>\int_{0}^{42} \frac{23}{42}x^{2} dx</math> Testseite, für interne Verwendung. <syntaxhighlight lang="php"> <?php ladida(); $var = fopen("foobar"); ?> </syntaxhighlight> [[Datei:Xkcd.png]] [[Datei:Xkcd.png|thumb]] [[Category:Elektronik]] 07b235173529e015cf5ddf976250cfe9feed6708 Datei:Gartenbrunnen-ltspice.png 6 247 662 2011-09-12T22:03:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Gartenbrunnen-ltspice-sim.png 6 248 663 2011-09-12T22:11:29Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Gartenbrunnen-brd.png 6 249 664 2011-09-12T22:18:02Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Gartenbrunnen-sch.png 6 250 665 2011-09-12T22:18:20Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Gartenbrunnen.zip 6 251 666 2011-09-12T22:28:39Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Gartenbrunnen 0 252 667 2011-09-12T22:30:36Z Chris 2 Seite erstellt wikitext text/x-wiki =Ausgangssituation= Meine Tante hat einen Gartenbrunnen, dessen solarbetriebene Pumpe ein etwas eigenwilliges Verhalten hat: Schaltet man sie unter Tags ein, funktioniert sie perfekt. Wenn eine Wolke vor die Sonne zieht, wird sie schwächer bis sie schließlich irgendwann ausgeht - wenn sich danach die Sonne wieder zeigt, läuft der Pumpe aber wieder. Am nächsten Tag ist die Freude am plätschernden Wasser aber vorbei - die Pumpe verweigert bis zum kurzzeitigen Ausschalten den Dienst. Der Hersteller kann sich das Phänomen nicht erklären. Ich stellte die Vermutung auf, dass das langsame Ansteigen der Versorgungsspannung den Brushlessmotor in eine ungünstige Stellung laufen lässt, aus der er nur noch durch einen Spannungspuls herauskommt. =Lösungssuche= Der Nachbar meiner Tante versuchte das Problem mit einem Elektrolytkondensator zu lösen - ohne Erfolg. Vermutlich lag es daran, dass die Pumpe bei steigener Spannung keine sprungartige Stromaufnahme zu verzeichnen hat, die der Kondensator kompensieren könnte. Meine Idee war ein primitiver Schwellenwertschalter, der die Pumpe erst mit Strom versorgen soll, wenn die Solarzelle genug Spannung (und somit auch Strom) liefert. Um den Punkt zu finden, wann die Pumpe zuverlässig einschaltet, klemmte ich mein Labornetzteil (ja, sowas habe ich im Urlaub dabei) an die Brunnenpumpe und drehte langsam die Spannung auf, bis etwas passierte. Bei etwa 13V sprudelte das Wasser langsam nach oben. =Lösungsversuch= Ok, ein primitiver Schwellenwertschalter. Der wahrscheinlich einfachste Weg dorthin ist ein Komparator mit Operationsverstärker. Da die Spannung der Solarzelle beim einschalten der Pumpe mit Sicherheit einbricht, muss die Schaltung zusätzlich eine Hysterese (oder etwas ähnliches) aufweisen. Zu meinem Pech konnte ich keine halbwegs einfache OP-Amp-Schaltung finden, die dieser Anforderung entspricht. Ich war auch schon kurz davor, das Problem mit einem kleinen Mikrocontroller zu erschlagen. Aber dieses mal sollte es etwas analoges sein! Warum also nicht einen einfachen Transistor verwenden, der einfach etwas träge schaltet? Also kurz LTspice angeworfen und nach gut Dünken gemalt: [[Datei:Gartenbrunnen-ltspice.png]] Herz der Geschichte ist die Z-Diode D1, die in der Simulation 10V abfallen lässt. Liegt an der Schaltung also etwa 10,7V an, fängt der Transistor Q1 damit an, den Widerstand R2 (großzügig primitiver Ersatz des Lastrelais) gegen Masse zu schalten. Verzögert wird der Vorgang durch den Kondensator C1, der zwar keine richtige Hysterese, dafür aber eine Verzögerung beim Ein- und Ausschalten des Relais erzeugt. Zur Schaltungssimulation fährt die Spannungsquelle V1 innerhalb von 5s eine Rampe von 0 auf 18V hoch, hält diese 1s und lässt die Spannung innerhalb von 10 Sekunden wieder auf 0V fallen: [[Datei:Gartenbrunne-ltspice-sim.png]] Hierbei ist V(n001) die Eingangsspannung und V(n002) die Spannung am Kollektor des Transistors. Der Einschaltpunkt des Relais liegt hier bei 12,6V, der Ausschaltpunkt bei 8,8V. Mit einer 12V Z-Diode entsprechend etwa (!) 2V höher. Der Stromlaufplan ist in EAGLE schnell gezeichnet und das Board gesetzt. Die längste Zeit braucht fast der Aufbau auf Lochraster (momentan kein Bild) <gallery> Datei:Gartenbrunnen-sch.png|Stromlaufplan Datei:Gartenbrunnen-brd.png|Board </gallery> Der Vorwiderstand für das Relais wurde empirisch ermittelt und lässt so viel Spannung abfallen, dass das 12V-Relais auch bei 18V Eingangsspannung noch nicht ins Schwitzen kommt. =Ergebnis= Um die Schaltung richtig zu testen stiefelte ich mitten in der Nacht in den Garten um die Schaltung zu installieren. Am nächsten morgen zeigte sich: nichts. Die Schaltung selbst funktionierte zwar wie gewünscht, erfüllte aber nicht ihren Zweck: die Pumpe zeigte sich gänzlich unbeeindruckt vom späteren Einschalten. Woran es lag habe ich nicht weiter erforscht, da der Hersteller der Pumpe bereits einen kostenlosen Umtausch anbot, von dem meine Verwandten nach dem winterbedingten Abbau des Brunnens wohl eingehen werden. Somit ist das Ergebnis schlichtweg die Erkenntnis, dass manchmal etwas einfach nicht will und man nicht jedes Problem technisch lösen muss ;-) =Download= Wer noch etwas mit LTspice oder den EAGLE-Dateien spielen will, ist herzlich eingeladen: [[Datei:Gartenbrunnen.zip]] [[Kategorie:Murks]] [[Kategorie:Vergurktes]] af3c795b60fef2f53952c9eb2526def39c2b04e4 668 667 2011-09-12T22:31:45Z Chris 2 nur ein Buchstabe fehlte... wikitext text/x-wiki =Ausgangssituation= Meine Tante hat einen Gartenbrunnen, dessen solarbetriebene Pumpe ein etwas eigenwilliges Verhalten hat: Schaltet man sie unter Tags ein, funktioniert sie perfekt. Wenn eine Wolke vor die Sonne zieht, wird sie schwächer bis sie schließlich irgendwann ausgeht - wenn sich danach die Sonne wieder zeigt, läuft der Pumpe aber wieder. Am nächsten Tag ist die Freude am plätschernden Wasser aber vorbei - die Pumpe verweigert bis zum kurzzeitigen Ausschalten den Dienst. Der Hersteller kann sich das Phänomen nicht erklären. Ich stellte die Vermutung auf, dass das langsame Ansteigen der Versorgungsspannung den Brushlessmotor in eine ungünstige Stellung laufen lässt, aus der er nur noch durch einen Spannungspuls herauskommt. =Lösungssuche= Der Nachbar meiner Tante versuchte das Problem mit einem Elektrolytkondensator zu lösen - ohne Erfolg. Vermutlich lag es daran, dass die Pumpe bei steigener Spannung keine sprungartige Stromaufnahme zu verzeichnen hat, die der Kondensator kompensieren könnte. Meine Idee war ein primitiver Schwellenwertschalter, der die Pumpe erst mit Strom versorgen soll, wenn die Solarzelle genug Spannung (und somit auch Strom) liefert. Um den Punkt zu finden, wann die Pumpe zuverlässig einschaltet, klemmte ich mein Labornetzteil (ja, sowas habe ich im Urlaub dabei) an die Brunnenpumpe und drehte langsam die Spannung auf, bis etwas passierte. Bei etwa 13V sprudelte das Wasser langsam nach oben. =Lösungsversuch= Ok, ein primitiver Schwellenwertschalter. Der wahrscheinlich einfachste Weg dorthin ist ein Komparator mit Operationsverstärker. Da die Spannung der Solarzelle beim einschalten der Pumpe mit Sicherheit einbricht, muss die Schaltung zusätzlich eine Hysterese (oder etwas ähnliches) aufweisen. Zu meinem Pech konnte ich keine halbwegs einfache OP-Amp-Schaltung finden, die dieser Anforderung entspricht. Ich war auch schon kurz davor, das Problem mit einem kleinen Mikrocontroller zu erschlagen. Aber dieses mal sollte es etwas analoges sein! Warum also nicht einen einfachen Transistor verwenden, der einfach etwas träge schaltet? Also kurz LTspice angeworfen und nach gut Dünken gemalt: [[Datei:Gartenbrunnen-ltspice.png]] Herz der Geschichte ist die Z-Diode D1, die in der Simulation 10V abfallen lässt. Liegt an der Schaltung also etwa 10,7V an, fängt der Transistor Q1 damit an, den Widerstand R2 (großzügig primitiver Ersatz des Lastrelais) gegen Masse zu schalten. Verzögert wird der Vorgang durch den Kondensator C1, der zwar keine richtige Hysterese, dafür aber eine Verzögerung beim Ein- und Ausschalten des Relais erzeugt. Zur Schaltungssimulation fährt die Spannungsquelle V1 innerhalb von 5s eine Rampe von 0 auf 18V hoch, hält diese 1s und lässt die Spannung innerhalb von 10 Sekunden wieder auf 0V fallen: [[Datei:Gartenbrunnen-ltspice-sim.png]] Hierbei ist V(n001) die Eingangsspannung und V(n002) die Spannung am Kollektor des Transistors. Der Einschaltpunkt des Relais liegt hier bei 12,6V, der Ausschaltpunkt bei 8,8V. Mit einer 12V Z-Diode entsprechend etwa (!) 2V höher. Der Stromlaufplan ist in EAGLE schnell gezeichnet und das Board gesetzt. Die längste Zeit braucht fast der Aufbau auf Lochraster (momentan kein Bild) <gallery> Datei:Gartenbrunnen-sch.png|Stromlaufplan Datei:Gartenbrunnen-brd.png|Board </gallery> Der Vorwiderstand für das Relais wurde empirisch ermittelt und lässt so viel Spannung abfallen, dass das 12V-Relais auch bei 18V Eingangsspannung noch nicht ins Schwitzen kommt. =Ergebnis= Um die Schaltung richtig zu testen stiefelte ich mitten in der Nacht in den Garten um die Schaltung zu installieren. Am nächsten morgen zeigte sich: nichts. Die Schaltung selbst funktionierte zwar wie gewünscht, erfüllte aber nicht ihren Zweck: die Pumpe zeigte sich gänzlich unbeeindruckt vom späteren Einschalten. Woran es lag habe ich nicht weiter erforscht, da der Hersteller der Pumpe bereits einen kostenlosen Umtausch anbot, von dem meine Verwandten nach dem winterbedingten Abbau des Brunnens wohl eingehen werden. Somit ist das Ergebnis schlichtweg die Erkenntnis, dass manchmal etwas einfach nicht will und man nicht jedes Problem technisch lösen muss ;-) =Download= Wer noch etwas mit LTspice oder den EAGLE-Dateien spielen will, ist herzlich eingeladen: [[Datei:Gartenbrunnen.zip]] [[Kategorie:Murks]] [[Kategorie:Vergurktes]] 5955bac53dc8f18677871f8dcc2b17c9d7029407 Modellbau-Leuchtstofflampe 0 254 670 2011-09-13T21:52:30Z Chris 2 Seite erstellt wikitext text/x-wiki Dass man im Modellbau - speziell bei Modellbahnen - möglichst nah an der Realität sein möchte, muss man wohl niemandem sagen. Durch mehr oder weniger Zufall bin ich auf eine Methode gekommen, mit der man Leuchtstofflampen relativ einfach nachbilden kann. Dazu benötigt man lediglich eine Heißklebepistole, einen Metallblock (oder einen dickeren Metallstreifen) und je Leuchtstofflampe eine LED. Der Bau erfolgt in drei einfachen Schritten: # Mit der Heißklebepistole 15mm lange und etwa 4mm breite Würstchen auf den (möglichst nicht allzu warmen) Metallblock ziehen # Die Würstchen nach dem vollständigen Aushärten vom Metall abziehen # Die LED mit Heißkleber (auf die LED anbringen) an die glatte Seite der Wurst ankleben <gallery> Datei:Leuchstoff1.jpg|LED mit aufgeklebtem Lightspreader Datei:Leuchstoff2.jpg|Andere Ansicht </gallery> Die beste Erfahrung machte ich mit 3mm-LEDs. SMD-LEDs funktionieren zwar auch, allerdings ist der Effekt dort nicht so stark, da bei den meisten keine Linse vorhanden ist oder zumindest die Abstrahlcharakteristik nicht ganz passt. <gallery> Datei:Leuchtstoff-bahnhof1.jpg|Mit 3mm-LEDs im Bahnhof Datei:Leuchtstoff-tanke1.jpg|Mit PLCC2-LEDs in einer Tankstelle </gallery> Bessere Fotos und mehr Details zur "Produktion" folgen noch [[Kategorie:Modellbau]] 44752b1ca7d8a93fc28317acc3e3b1e7f4792eab 671 670 2011-09-13T21:57:26Z Chris 2 wikitext text/x-wiki Dass man im Modellbau - speziell bei Modellbahnen - möglichst nah an der Realität sein möchte, muss man wohl niemandem sagen. Durch mehr oder weniger Zufall bin ich auf eine Methode gekommen, mit der man Leuchtstofflampen relativ einfach nachbilden kann. Dazu benötigt man lediglich eine Heißklebepistole, einen Metallblock (oder einen dickeren Metallstreifen) und je Leuchtstofflampe eine LED. Der Bau erfolgt in drei einfachen Schritten: # Mit der Heißklebepistole 15mm lange und etwa 4mm breite Würstchen auf den (möglichst nicht allzu warmen) Metallblock ziehen # Die Würstchen nach dem vollständigen Aushärten vom Metall abziehen # Die LED mit Heißkleber (auf die LED anbringen) an die glatte Seite der Wurst ankleben <gallery> Datei:Leuchtstoff1.jpg|LED mit aufgeklebtem Lightspreader Datei:Leuchtstoff2.jpg|Andere Ansicht </gallery> Die beste Erfahrung machte ich mit 3mm-LEDs. SMD-LEDs funktionieren zwar auch, allerdings ist der Effekt dort nicht so stark, da bei den meisten keine Linse vorhanden ist oder zumindest die Abstrahlcharakteristik nicht ganz passt. <gallery> Datei:Leuchtstoff-bahnhof1.jpg|Mit 3mm-LEDs im Bahnhof Datei:Leuchtstoff-tanke1.jpg|Mit PLCC2-LEDs in einer Tankstelle </gallery> Bessere Fotos und mehr Details zur "Produktion" folgen noch [[Kategorie:Modellbau]] 47c3230cc7fef0cede00d26914a8a6586ca84e81 Datei:Leuchtstoff1.jpg 6 255 672 2011-09-13T21:57:45Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Leuchtstoff-bahnhof1.jpg 6 257 674 2011-09-13T21:58:21Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Leuchtstoff-tanke1.jpg 6 258 675 2011-09-13T21:58:40Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Leuchtstoff2.jpg 6 259 676 2011-09-13T22:00:44Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Touchlight 0 92 678 470 2011-09-16T13:14:06Z Chris 2 wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny13 | Takt = 9,6 | FuseH = FF | FuseL = 7A }} Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. = Leuchtmittel = Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "ultrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos selektieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen, der über zwei Hardware-PWMs verfügt. Um diese auch nutzen zu können, wird die LED-Leiste in zwei Stränge unterteilt. Die Anzahl der LEDs wird einzig durch das Netzteil beschränkt (ein austemustertes SonyEricsson-Ladegerät). Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. = Bedienung = Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. [Kategorie:AVR] Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. = Theorie = [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> :<math>U\left(t\right) = U_{0} \cdot \left(1-e^{\frac{-t}{R \cdot C}}\right)</math> Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. = Praxis = Um es noch ein wenig anschaulicher zu machen, habe ich das Oszilloskop auf die Schaltung angesetzt. Dazu wurde die Schaltung auf dem Breadboard aufgebaut. Die Ladewiderstände entsprechen wie im Schaltplan 1,1MOhm. Die Sensorfläche mit 28x28mm (7,8 cm²) und 1,5mm Dicke (Dielektrikum: Hartpapier) ist mit 5cm Leitung direkt (ohne Angstwiderstand) mit dem AVR verbunden. Aufgrund der nicht zu verachtenden Kapazität des Breadboards un des Tastkopfes (Impedanz weiß ich gerade nicht auswendig) dürften die Messwerte deutlich verzerrt sein! Die Bilder und Erklärungen dienen daher höchstens zum Veranschaulichen des vorherigen Abschnitts! <gallery> Bild:Touchlight untouched.png|Unberührte Sensorfläche Bild:Touchlight touched.png|Berührte Sensorfläche Bild:Touchlight burst untuched.png|"Abfrageburst" unberührt Bild:Touchlight burst touched.png|"Abfrageburst" berührt </gallery> Im ersten Bild ist der Spannungsverlauf zu sehen, bei dem die Sensorfläche nicht berührt wurde. Entgegen der Datenblattangabe erkennt der AVR den High-Pegel bei 2,58V, wobei es 26,6µs dauert, bis dieser Wert erreicht wird. Wird die komplette Sensorfläche mit der Hand abgedeckt, steigt die Dauer bis zum Schwellenwert auf 41µs, also etwa das 1,5-fache der Zeit der unberührten Sensorfläche. Bei einem CPU-Takt von 9,6MHz sind dies 394 Taktzyklen (im Vergleich zu 256 Taktzyklen vorher), die man recht entspannt messen kann. In den letzten beiden Bildern ist ein kompletter "Abfrageburst" (5 Einzelabfragen) zu sehen. Auch wenn es auf den ersten Blick irreführend ist, die Bildunterschriften sind korrekt. Bei den beiden Fotos habe ich (dummerweise) eine andere Zeitbasis gewählt. Auch bei den Bursts hat das Zeitverhältnis zwischen unberührt und berührt den Faktor 1,5. Wobei ich dazu sagen muss: '''Traue keiner Statistik, die du nicht selbst gefälscht hast!''' Die gemessenen Dauern schwanken insbesondere beim Berühren der Sensorfläche immens. Hauptursache dürfte wahrscheinlich der Elektrosmog sein, der die 50 bzw. 100Hz (Halbwellen) aus dem Stromnetz beisteuert... = Die Software = Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <pre> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~pin; //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & pin) && --sampletime); //Zeit messen KEYDDR |= pin; //Pin als Ausgang -> entladen return sampletime; } </pre> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <pre> ... i = 0; n = 6; while(--n) { i += getcap(1<<PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </pre> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <pre> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </pre> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. == Download == [[Datei:Touch_1.0.zip]] Enthält sowohl den simplen Touchsensor als auch die Version mit serieller Ausgabe. CPU-Takt muss jeweils 9,6MHz sein (Bei Fabrikneuen Tiny13ern muss die CKDIV8-Fuse entfernt werden, damit das Teil bei vollem Takt läuft), der Rest nach eigenem Ermessen. Stromlaufpläne ist bei beiden Sourcen gleich, bei TouchSense ist zusätzlich der (nicht-invertierte) UART auf PBO. Dort werden die Messwerte der beiden Sensoren Tab-getrennt ausgegeben. die Konstante MINDELAY für den UART-Pause in suart.c muss wahrscheinlich angepasst werden. [[Category:AVR]] a761ad9f9795c75eafea7e774ea393264268ff64 679 678 2011-09-16T13:14:31Z Chris 2 /* Bedienung */ wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny13 | Takt = 9,6 | FuseH = FF | FuseL = 7A }} Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. = Leuchtmittel = Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "ultrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos selektieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen, der über zwei Hardware-PWMs verfügt. Um diese auch nutzen zu können, wird die LED-Leiste in zwei Stränge unterteilt. Die Anzahl der LEDs wird einzig durch das Netzteil beschränkt (ein austemustertes SonyEricsson-Ladegerät). Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. = Bedienung = Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. = Theorie = [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> :<math>U\left(t\right) = U_{0} \cdot \left(1-e^{\frac{-t}{R \cdot C}}\right)</math> Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. = Praxis = Um es noch ein wenig anschaulicher zu machen, habe ich das Oszilloskop auf die Schaltung angesetzt. Dazu wurde die Schaltung auf dem Breadboard aufgebaut. Die Ladewiderstände entsprechen wie im Schaltplan 1,1MOhm. Die Sensorfläche mit 28x28mm (7,8 cm²) und 1,5mm Dicke (Dielektrikum: Hartpapier) ist mit 5cm Leitung direkt (ohne Angstwiderstand) mit dem AVR verbunden. Aufgrund der nicht zu verachtenden Kapazität des Breadboards un des Tastkopfes (Impedanz weiß ich gerade nicht auswendig) dürften die Messwerte deutlich verzerrt sein! Die Bilder und Erklärungen dienen daher höchstens zum Veranschaulichen des vorherigen Abschnitts! <gallery> Bild:Touchlight untouched.png|Unberührte Sensorfläche Bild:Touchlight touched.png|Berührte Sensorfläche Bild:Touchlight burst untuched.png|"Abfrageburst" unberührt Bild:Touchlight burst touched.png|"Abfrageburst" berührt </gallery> Im ersten Bild ist der Spannungsverlauf zu sehen, bei dem die Sensorfläche nicht berührt wurde. Entgegen der Datenblattangabe erkennt der AVR den High-Pegel bei 2,58V, wobei es 26,6µs dauert, bis dieser Wert erreicht wird. Wird die komplette Sensorfläche mit der Hand abgedeckt, steigt die Dauer bis zum Schwellenwert auf 41µs, also etwa das 1,5-fache der Zeit der unberührten Sensorfläche. Bei einem CPU-Takt von 9,6MHz sind dies 394 Taktzyklen (im Vergleich zu 256 Taktzyklen vorher), die man recht entspannt messen kann. In den letzten beiden Bildern ist ein kompletter "Abfrageburst" (5 Einzelabfragen) zu sehen. Auch wenn es auf den ersten Blick irreführend ist, die Bildunterschriften sind korrekt. Bei den beiden Fotos habe ich (dummerweise) eine andere Zeitbasis gewählt. Auch bei den Bursts hat das Zeitverhältnis zwischen unberührt und berührt den Faktor 1,5. Wobei ich dazu sagen muss: '''Traue keiner Statistik, die du nicht selbst gefälscht hast!''' Die gemessenen Dauern schwanken insbesondere beim Berühren der Sensorfläche immens. Hauptursache dürfte wahrscheinlich der Elektrosmog sein, der die 50 bzw. 100Hz (Halbwellen) aus dem Stromnetz beisteuert... = Die Software = Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <pre> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~pin; //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & pin) && --sampletime); //Zeit messen KEYDDR |= pin; //Pin als Ausgang -> entladen return sampletime; } </pre> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <pre> ... i = 0; n = 6; while(--n) { i += getcap(1<<PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </pre> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <pre> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </pre> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. == Download == [[Datei:Touch_1.0.zip]] Enthält sowohl den simplen Touchsensor als auch die Version mit serieller Ausgabe. CPU-Takt muss jeweils 9,6MHz sein (Bei Fabrikneuen Tiny13ern muss die CKDIV8-Fuse entfernt werden, damit das Teil bei vollem Takt läuft), der Rest nach eigenem Ermessen. Stromlaufpläne ist bei beiden Sourcen gleich, bei TouchSense ist zusätzlich der (nicht-invertierte) UART auf PBO. Dort werden die Messwerte der beiden Sensoren Tab-getrennt ausgegeben. die Konstante MINDELAY für den UART-Pause in suart.c muss wahrscheinlich angepasst werden. [[Category:AVR]] b655da323b01a0ac2e899d36a4ba29d0ee70b774 Datei:Gartenbrunnen-real.jpg 6 260 680 2011-09-20T18:20:28Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Gartenbrunnen 0 252 681 668 2011-09-20T18:21:19Z Chris 2 Bild hinzugefügt wikitext text/x-wiki =Ausgangssituation= Meine Tante hat einen Gartenbrunnen, dessen solarbetriebene Pumpe ein etwas eigenwilliges Verhalten hat: Schaltet man sie unter Tags ein, funktioniert sie perfekt. Wenn eine Wolke vor die Sonne zieht, wird sie schwächer bis sie schließlich irgendwann ausgeht - wenn sich danach die Sonne wieder zeigt, läuft der Pumpe aber wieder. Am nächsten Tag ist die Freude am plätschernden Wasser aber vorbei - die Pumpe verweigert bis zum kurzzeitigen Ausschalten den Dienst. Der Hersteller kann sich das Phänomen nicht erklären. Ich stellte die Vermutung auf, dass das langsame Ansteigen der Versorgungsspannung den Brushlessmotor in eine ungünstige Stellung laufen lässt, aus der er nur noch durch einen Spannungspuls herauskommt. =Lösungssuche= Der Nachbar meiner Tante versuchte das Problem mit einem Elektrolytkondensator zu lösen - ohne Erfolg. Vermutlich lag es daran, dass die Pumpe bei steigener Spannung keine sprungartige Stromaufnahme zu verzeichnen hat, die der Kondensator kompensieren könnte. Meine Idee war ein primitiver Schwellenwertschalter, der die Pumpe erst mit Strom versorgen soll, wenn die Solarzelle genug Spannung (und somit auch Strom) liefert. Um den Punkt zu finden, wann die Pumpe zuverlässig einschaltet, klemmte ich mein Labornetzteil (ja, sowas habe ich im Urlaub dabei) an die Brunnenpumpe und drehte langsam die Spannung auf, bis etwas passierte. Bei etwa 13V sprudelte das Wasser langsam nach oben. =Lösungsversuch= Ok, ein primitiver Schwellenwertschalter. Der wahrscheinlich einfachste Weg dorthin ist ein Komparator mit Operationsverstärker. Da die Spannung der Solarzelle beim einschalten der Pumpe mit Sicherheit einbricht, muss die Schaltung zusätzlich eine Hysterese (oder etwas ähnliches) aufweisen. Zu meinem Pech konnte ich keine halbwegs einfache OP-Amp-Schaltung finden, die dieser Anforderung entspricht. Ich war auch schon kurz davor, das Problem mit einem kleinen Mikrocontroller zu erschlagen. Aber dieses mal sollte es etwas analoges sein! Warum also nicht einen einfachen Transistor verwenden, der einfach etwas träge schaltet? Also kurz LTspice angeworfen und nach gut Dünken gemalt: [[Datei:Gartenbrunnen-ltspice.png]] Herz der Geschichte ist die Z-Diode D1, die in der Simulation 10V abfallen lässt. Liegt an der Schaltung also etwa 10,7V an, fängt der Transistor Q1 damit an, den Widerstand R2 (großzügig primitiver Ersatz des Lastrelais) gegen Masse zu schalten. Verzögert wird der Vorgang durch den Kondensator C1, der zwar keine richtige Hysterese, dafür aber eine Verzögerung beim Ein- und Ausschalten des Relais erzeugt. Zur Schaltungssimulation fährt die Spannungsquelle V1 innerhalb von 5s eine Rampe von 0 auf 18V hoch, hält diese 1s und lässt die Spannung innerhalb von 10 Sekunden wieder auf 0V fallen: [[Datei:Gartenbrunnen-ltspice-sim.png]] Hierbei ist V(n001) die Eingangsspannung und V(n002) die Spannung am Kollektor des Transistors. Der Einschaltpunkt des Relais liegt hier bei 12,6V, der Ausschaltpunkt bei 8,8V. Mit einer 12V Z-Diode entsprechend etwa (!) 2V höher. Der Stromlaufplan ist in EAGLE schnell gezeichnet und das Board gesetzt. Die längste Zeit braucht fast der Aufbau auf Lochraster (momentan kein Bild) <gallery> Datei:Gartenbrunnen-sch.png|Stromlaufplan Datei:Gartenbrunnen-brd.png|Board Datei:Gartenbrunnen-real.jpg|Aufgebaut </gallery> Der Vorwiderstand für das Relais wurde empirisch ermittelt und lässt so viel Spannung abfallen, dass das 12V-Relais auch bei 18V Eingangsspannung noch nicht ins Schwitzen kommt. =Ergebnis= Um die Schaltung richtig zu testen stiefelte ich mitten in der Nacht in den Garten um die Schaltung zu installieren. Am nächsten morgen zeigte sich: nichts. Die Schaltung selbst funktionierte zwar wie gewünscht, erfüllte aber nicht ihren Zweck: die Pumpe zeigte sich gänzlich unbeeindruckt vom späteren Einschalten. Woran es lag habe ich nicht weiter erforscht, da der Hersteller der Pumpe bereits einen kostenlosen Umtausch anbot, von dem meine Verwandten nach dem winterbedingten Abbau des Brunnens wohl eingehen werden. Somit ist das Ergebnis schlichtweg die Erkenntnis, dass manchmal etwas einfach nicht will und man nicht jedes Problem technisch lösen muss ;-) =Download= Wer noch etwas mit LTspice oder den EAGLE-Dateien spielen will, ist herzlich eingeladen: [[Datei:Gartenbrunnen.zip]] [[Kategorie:Murks]] [[Kategorie:Vergurktes]] 4509cd79190459807eb689dd0ecfd303f2c20088 691 681 2011-12-11T23:15:32Z Chris 2 Typo/Grammatik wikitext text/x-wiki =Ausgangssituation= Meine Tante hat einen Gartenbrunnen, dessen solarbetriebene Pumpe ein etwas eigenwilliges Verhalten hat: Schaltet man sie unter Tags ein, funktioniert sie perfekt. Wenn eine Wolke vor die Sonne zieht, wird sie schwächer bis sie schließlich irgendwann ausgeht - wenn sich danach die Sonne wieder zeigt, läuft der Pumpe aber wieder. Am nächsten Tag ist die Freude am plätschernden Wasser aber vorbei - die Pumpe verweigert vor einem kurzzeitigen Ausschalten den Dienst. Der Hersteller kann sich das Phänomen nicht erklären. Ich stellte die Vermutung auf, dass das langsame Ansteigen der Versorgungsspannung den Brushlessmotor in eine ungünstige Stellung laufen lässt, aus der er nur noch durch einen Spannungspuls herauskommt. =Lösungssuche= Der Nachbar meiner Tante versuchte das Problem mit einem Elektrolytkondensator zu lösen - ohne Erfolg. Vermutlich lag es daran, dass die Pumpe bei steigener Spannung keine sprungartige Stromaufnahme zu verzeichnen hat, die der Kondensator kompensieren könnte. Meine Idee war ein primitiver Schwellenwertschalter, der die Pumpe erst mit Strom versorgen soll, wenn die Solarzelle genug Spannung (und somit auch Strom) liefert. Um den Punkt zu finden, wann die Pumpe zuverlässig einschaltet, klemmte ich mein Labornetzteil (ja, sowas habe ich im Urlaub dabei) an die Brunnenpumpe und drehte langsam die Spannung auf, bis etwas passierte. Bei etwa 13V sprudelte das Wasser langsam nach oben. =Lösungsversuch= Ok, ein primitiver Schwellenwertschalter. Der wahrscheinlich einfachste Weg dorthin ist ein Komparator mit Operationsverstärker. Da die Spannung der Solarzelle beim Einschalten der Pumpe mit Sicherheit einbricht, muss die Schaltung zusätzlich eine Hysterese (oder etwas ähnliches) aufweisen. Zu meinem Pech konnte ich keine halbwegs einfache OP-Amp-Schaltung finden, die diese Anforderung erfüllt. Ich war auch schon kurz davor, das Problem mit einem kleinen Mikrocontroller zu erschlagen. Aber dieses mal sollte es etwas analoges sein! Warum also nicht einen einfachen Transistor verwenden, der einfach etwas träge schaltet? Also kurz LTspice angeworfen und nach gut Dünken gemalt: [[Datei:Gartenbrunnen-ltspice.png]] Herz der Geschichte ist die Z-Diode D1, die in der Simulation 10V abfallen lässt. Liegt an der Schaltung also etwa 10,7V an, fängt der Transistor Q1 damit an, den Widerstand R2 (großzügig primitiver Ersatz des Lastrelais) gegen Masse zu schalten. Verzögert wird der Vorgang durch den Kondensator C1, der zwar keine richtige Hysterese, dafür aber eine Verzögerung beim Ein- und Ausschalten des Relais erzeugt. Zur Schaltungssimulation fährt die Spannungsquelle V1 innerhalb von 5s eine Rampe von 0 auf 18V hoch, hält diese 1s und lässt die Spannung innerhalb von 10 Sekunden wieder auf 0V fallen: [[Datei:Gartenbrunnen-ltspice-sim.png]] Hierbei ist V(n001) die Eingangsspannung und V(n002) die Spannung am Kollektor des Transistors. Der Einschaltpunkt des Relais liegt hier bei 12,6V, der Ausschaltpunkt bei 8,8V. Mit einer 12V Z-Diode entsprechend etwa (!) 2V höher. Der Stromlaufplan ist in EAGLE schnell gezeichnet und das Board gesetzt. Die längste Zeit braucht fast der Aufbau auf Lochraster: <gallery> Datei:Gartenbrunnen-sch.png|Stromlaufplan Datei:Gartenbrunnen-brd.png|Board Datei:Gartenbrunnen-real.jpg|Aufgebaut </gallery> Der Vorwiderstand für das Relais wurde empirisch ermittelt und lässt so viel Spannung abfallen, dass das 12V-Relais auch bei 18V Eingangsspannung noch nicht ins Schwitzen kommt. =Ergebnis= Um die Schaltung richtig zu testen stiefelte ich mitten in der Nacht in den Garten um die Schaltung zu installieren. Am nächsten morgen zeigte sich: nichts. Die Schaltung selbst funktionierte zwar wie gewünscht, erfüllte aber nicht ihren Zweck: die Pumpe zeigte sich gänzlich unbeeindruckt vom späteren Einschalten. Woran es lag habe ich nicht weiter erforscht, da der Hersteller der Pumpe bereits einen kostenlosen Umtausch anbot, von dem meine Verwandten nach dem winterbedingten Abbau des Brunnens wohl eingehen werden. Somit ist das Ergebnis schlichtweg die Erkenntnis, dass manchmal etwas einfach nicht will und man nicht jedes Problem technisch lösen muss ;-) =Download= Wer noch etwas mit LTspice oder den EAGLE-Dateien spielen will, ist herzlich eingeladen: [[Datei:Gartenbrunnen.zip]] [[Kategorie:Murks]] [[Kategorie:Vergurktes]] 7bc426ddf254cd401f1022a4a15a5c338962f652 Datei:Audioslave config.png 6 261 682 2011-10-03T18:47:44Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Audioslave tray.png 6 262 683 2011-10-03T18:48:04Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Audioslave servo.jpg 6 263 684 2011-10-03T18:48:18Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Audioslave servo2.jpg 6 264 685 2011-10-03T18:48:31Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Audioslave servo3.jpg 6 265 686 2011-10-03T18:48:36Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Audioslave.zip 6 266 687 2011-10-03T18:56:17Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Audioslave 0 267 688 2011-10-03T19:05:00Z Chris 2 Seite erstellt wikitext text/x-wiki =Ausgangssituation= Ich habe schon seit einigen Jahren eine 5.1-Anlage an meinem PC hängen, mit der ich auch sehr zufrieden bin. Diese wird - wie der Computer selbst - von einem Hauptschalter getrennt, wenn das Gesamtsystem nicht verwendet wird. Wie der [http://www.teufel.de Teufel] (höhö) so will, möchte man das Ding manchmal auch ruhig haben (z. B. beim Telefonieren) oder man braucht sie nicht, weil man gar nicht da ist. Zwar hat der Verstärker eine "Auto-Funktion", bei der er bei Stille nach einer gewissen Zeit in den Standby geht. Dummerweise unterbindet sie die Beschallung auch, wenn man mal leise Musik hören möchte. Bis jetzt bin ich oft unter den Tisch gekrochen (der Verstärker ist im Subwoofer), um die Einstellung zu ändern, aber wie das so ist: spätestens das Abschalten vergisst man. =Idee= Wie schon beim alten Fernseher lässt sich auch hier Faulheit und Nachlässigkeit durch Technik ersetzen. Gleichzeitig soll wieder gelten: so wenig wie möglich am eigentlichen Gerät umbauen. Da es sich bei dem Schalter um einen gut erreichbaren - und halbwegs leichtgängigem - Schiebeschalter handelt, lag die Idee nah, einen Modellbauservo zu verwenden. In der Grabbelkiste lagen noch ein paar, so könnte die Bastelei beginnen. =Lösung= ==Hardware== {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = DD | FuseL = E1 | FuseE = FF }} Da ich möglichst wenig Änderungen am Verstärker vornehmen wollte, fiel die erste Aufmerksamkeit auf die Befestigung: Der Amp ist ringsum mit Holzschrauben im Gehäuse befestigt - also auch wenige Zentimeter über dem Powerschalter. Ein Stück Platinenmaterial sorgt für den Halt am Gehäuse. Der Servo selbst wird ebenfalls von einem Stück Platine gehalten. Die Abstandshalter zwischen Halteplatte und Servo bestehen - wie kanns auch anders sein - auch aus FR4-Basismaterial. Zum Verbinden des 3D-Puzzles wird der Lötkolben mit einer gehörigen Portion Lötzinn verwendet. Einzige Voraussetzung hierfür ist eine gewisse Leistung des Lötkolbens. Unter 50 Watt kann man es sicher versuchen, es macht aber sicher nicht allzu viel Spaß. <gallery> Datei:Audioslave_servo.jpg|Servomotor im Rahmen, ungeschraubt Datei:Audioslave_servo2.jpg|Zusammengebaut mit Montageplatte Datei:Audioslave_servo3.jpg|Am Verstärker angeschraubt </gallery> Nachdem der mechanische Part passt, kommt nun der doch etwas aufwendigere Teil: die Software. Damit man das Teil nicht wieder vergessen kann, ist die Anbindung an den PC und eine gewisse Intelligenz Pflicht. Hier kommt Hardwareseitig (wieder mal) V-USB zum Einsatz. Die Ansteuerung des Motors, die natürlich auch vom AVR übernimmen wird, ist denkbar einfach: Der Regler im Servo erwartet Pulse zwischen 1 und 2ms Länge, wobei er bei 1ms das "Ruder" vollständig in die eine, bei 2ms vollständig in die andere Richtung ausschlagen lässt. Bei der Wiederholfrequenz haben sich 50Hz eingebürgert, was bei meinem einfachen Servo insoweit wichtig ist, dass das Teil ohne Pulse weder die gewünschte Position hält, noch vollständig anfährt, falls sie noch nicht erreicht wurde. Bei den neueren (und teureren) "Digitalservos" ist das nicht der Fall. Aber das tut hier weniger zur Sache. Die V-USB-Bibliothek emuliert ein HID, wodurch betriebssystemseitig keine speziellen Treiber erforderlich sind. Aufgrund der Unkomplexität ist der HID-Report lediglich 2 Byte groß. Das erste gibt die Position an, das zweite, wie lange die Ausgabe aktiv sein soll - also wie Lange der Motor mit aller Kraft versucht, zu seinem Ziel zu kommen. ==Software== Die PC-Software gestaltete sich als ein bisschen schwieriger. Zwar ist C# relativ einfach, aber das .NET-Framework bietet von sich aus keine Schnittstelle zum Audiomixer von Windows an und alle Beispiele und Bibliotheken die ich fand waren nicht mit Win7 x64 kompatibel... Nach längerer Sucherei stieß ich endlich auf die [http://www.codeproject.com/KB/vista/CoreAudio.aspx Core Audio API], die zumindest mit 64 Bit prima funktioniert. Ein wenig (unausgegorenen) Quellcode außenrum und ein paar Icons von Windows "ausgeliehen" und "fertig" (ein paar Funktionen fehlen noch) ist das Programm: <gallery> Datei:Audioslave_tray.png|Trayicon mit Menü Datei:Audioslave_config.png|Konfigurationsfenster </gallery> Es kennt zwei Modi zum Abschalten des Verstärker - reagieren auf Mute, also abschalten wenn auf der Tastatur oder im Mixer das ausgewählte Gerät auf Mute geschalten wird sowie reagieren auf Stille. Dazu wird periodisch die Ausgabelautstärke erfasst, ist diese für den eingestellten Zeitraum unter dem angegebenen Schwellenwert gehen ebenfalls die Lichter aus. Zusätzlich kann man die Anlage manuell ein- und ausschalten. =Tivia= * Ursprünglich wollte ich die Firmware mit AVR Studio 5 schreiben. Aus mir noch unbekannten Gründen lässt sich damit V-USB nicht kompilieren * Die Hardware funktionierte auf dem Steckbrett prima, auf Lochraster im ersten Versuch (und nach zwei Änderungen) überhaupt nicht. Deshalb gibt es noch keinen Stromlaufplan. * Ursprünglich sollte die Hauptarbeit im C#-Programm in Program.cs stattfinden. Allerdings lassen sich innerhalb von Eventhandlern scheinbar keine Timer starten - die wollen über Invoke bedient werden. Da es in der Popelklasse kein Invoke gibt, ging der ganze in ein Dummyform. Nicht schön, funktioniert aber. * Nach dem Speichern der Einstellungen sollte man das Programm neu starten. Hauptsächlich da ich zu faul war die entsprechenden Routinen zu schreiben. Abgesehen davon funktioniert eigentlich alles. Wenn etwas nicht funktioniert: Exceptions werden nicht abgefangen. =Download= [[Datei:Audioslave.zip]] [[Kategorie:Software]] [[Kategorie:PC]] [[Kategorie:PC]] 1e94cede2dad70df01525296c82b5086e5c77246 690 688 2011-10-03T19:11:50Z Chris 2 Verweis auf den [[Panasonic-Zapper]] hinzugefügt wikitext text/x-wiki =Ausgangssituation= Ich habe schon seit einigen Jahren eine 5.1-Anlage an meinem PC hängen, mit der ich auch sehr zufrieden bin. Diese wird - wie der Computer selbst - von einem Hauptschalter getrennt, wenn das Gesamtsystem nicht verwendet wird. Wie der [http://www.teufel.de Teufel] (höhö) so will, möchte man das Ding manchmal auch ruhig haben (z. B. beim Telefonieren) oder man braucht sie nicht, weil man gar nicht da ist. Zwar hat der Verstärker eine "Auto-Funktion", bei der er bei Stille nach einer gewissen Zeit in den Standby geht. Dummerweise unterbindet sie die Beschallung auch, wenn man mal leise Musik hören möchte. Bis jetzt bin ich oft unter den Tisch gekrochen (der Verstärker ist im Subwoofer), um die Einstellung zu ändern, aber wie das so ist: spätestens das Abschalten vergisst man. =Idee= Wie schon beim [[Panasonic-Zapper|alten Fernseher]] lässt sich auch hier Faulheit und Nachlässigkeit durch Technik ersetzen. Gleichzeitig soll wieder gelten: so wenig wie möglich am eigentlichen Gerät umbauen. Da es sich bei dem Schalter um einen gut erreichbaren - und halbwegs leichtgängigem - Schiebeschalter handelt lag die Idee nah, einen Modellbauservo zu verwenden. In der Grabbelkiste lagen noch ein paar, so könnte die Bastelei beginnen. =Lösung= ==Hardware== {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = DD | FuseL = E1 | FuseE = FF }} Da ich möglichst wenig Änderungen am Verstärker vornehmen wollte, fiel die erste Aufmerksamkeit auf die Befestigung: Der Amp ist ringsum mit Holzschrauben im Gehäuse befestigt - also auch wenige Zentimeter über dem Powerschalter. Ein Stück Platinenmaterial sorgt für den Halt am Gehäuse. Der Servo selbst wird ebenfalls von einem Stück Platine gehalten. Die Abstandshalter zwischen Halteplatte und Servo bestehen - wie kanns auch anders sein - auch aus FR4-Basismaterial. Zum Verbinden des 3D-Puzzles wird der Lötkolben mit einer gehörigen Portion Lötzinn verwendet. Einzige Voraussetzung hierfür ist eine gewisse Leistung des Lötkolbens. Unter 50 Watt kann man es sicher versuchen, es macht aber sicher nicht allzu viel Spaß. <gallery> Datei:Audioslave_servo.jpg|Servomotor im Rahmen, ungeschraubt Datei:Audioslave_servo2.jpg|Zusammengebaut mit Montageplatte Datei:Audioslave_servo3.jpg|Am Verstärker angeschraubt </gallery> Nachdem der mechanische Part passt, kommt nun der doch etwas aufwendigere Teil: die Software. Damit man das Teil nicht wieder vergessen kann, ist die Anbindung an den PC und eine gewisse Intelligenz Pflicht. Hier kommt Hardwareseitig (wieder mal) V-USB zum Einsatz. Die Ansteuerung des Motors, die natürlich auch vom AVR übernimmen wird, ist denkbar einfach: Der Regler im Servo erwartet Pulse zwischen 1 und 2ms Länge, wobei er bei 1ms das "Ruder" vollständig in die eine, bei 2ms vollständig in die andere Richtung ausschlagen lässt. Bei der Wiederholfrequenz haben sich 50Hz eingebürgert, was bei meinem einfachen Servo insoweit wichtig ist, dass das Teil ohne Pulse weder die gewünschte Position hält, noch vollständig anfährt, falls sie noch nicht erreicht wurde. Bei den neueren (und teureren) "Digitalservos" ist das nicht der Fall. Aber das tut hier weniger zur Sache. Die V-USB-Bibliothek emuliert ein HID, wodurch betriebssystemseitig keine speziellen Treiber erforderlich sind. Aufgrund der Unkomplexität ist der HID-Report lediglich 2 Byte groß. Das erste gibt die Position an, das zweite, wie lange die Ausgabe aktiv sein soll - also wie Lange der Motor mit aller Kraft versucht, zu seinem Ziel zu kommen. ==Software== Die PC-Software gestaltete sich als ein bisschen schwieriger. Zwar ist C# relativ einfach, aber das .NET-Framework bietet von sich aus keine Schnittstelle zum Audiomixer von Windows an und alle Beispiele und Bibliotheken die ich fand waren nicht mit Win7 x64 kompatibel... Nach längerer Sucherei stieß ich endlich auf die [http://www.codeproject.com/KB/vista/CoreAudio.aspx Core Audio API], die zumindest mit 64 Bit prima funktioniert. Ein wenig (unausgegorenen) Quellcode außenrum und ein paar Icons von Windows "ausgeliehen" und "fertig" (ein paar Funktionen fehlen noch) ist das Programm: <gallery> Datei:Audioslave_tray.png|Trayicon mit Menü Datei:Audioslave_config.png|Konfigurationsfenster </gallery> Es kennt zwei Modi zum Abschalten des Verstärker - reagieren auf Mute, also abschalten wenn auf der Tastatur oder im Mixer das ausgewählte Gerät auf Mute geschalten wird sowie reagieren auf Stille. Dazu wird periodisch die Ausgabelautstärke erfasst, ist diese für den eingestellten Zeitraum unter dem angegebenen Schwellenwert gehen ebenfalls die Lichter aus. Zusätzlich kann man die Anlage manuell ein- und ausschalten. =Tivia= * Ursprünglich wollte ich die Firmware mit AVR Studio 5 schreiben. Aus mir noch unbekannten Gründen lässt sich damit V-USB nicht kompilieren * Die Hardware funktionierte auf dem Steckbrett prima, auf Lochraster im ersten Versuch (und nach zwei Änderungen) überhaupt nicht. Deshalb gibt es noch keinen Stromlaufplan. * Ursprünglich sollte die Hauptarbeit im C#-Programm in Program.cs stattfinden. Allerdings lassen sich innerhalb von Eventhandlern scheinbar keine Timer starten - die wollen über Invoke bedient werden. Da es in der Popelklasse kein Invoke gibt, ging der ganze in ein Dummyform. Nicht schön, funktioniert aber. * Nach dem Speichern der Einstellungen sollte man das Programm neu starten. Hauptsächlich da ich zu faul war die entsprechenden Routinen zu schreiben. Abgesehen davon funktioniert eigentlich alles. Wenn etwas nicht funktioniert: Exceptions werden nicht abgefangen. =Download= [[Datei:Audioslave.zip]] [[Kategorie:Software]] [[Kategorie:PC]] [[Kategorie:PC]] d6862233cfd8f22fe8e84be1f24edd230c3bf708 Hauptseite 0 1 689 677 2011-10-03T19:08:42Z Chris 2 Aktualisiert wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] *12.06.2011 [[Maschinenleuchte]] *04.05.2011 [[ECL-Bus-Decoder]] *19.03.2011 [[Physik-Formelsammlung]] =Updates= *19.03.2010 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll 40e20552cf9dff874e5c37420d2092c42092a8d9 708 689 2011-12-29T14:25:43Z Chris 2 Neues! wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] *12.06.2011 [[Maschinenleuchte]] *04.05.2011 [[ECL-Bus-Decoder]] =Updates= *19.03.2010 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung → Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll cb102591d74611329aa99c777e7755cd64edf6c6 730 708 2012-03-14T21:19:17Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *12.03.2012 [[EMR7373]] (noch im entstehen) *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] *12.06.2011 [[Maschinenleuchte]] =Updates= *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit 6834c689699c3a61b910d6c835d94a933b6002ce 731 730 2012-03-14T21:19:32Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *12.03.2012 [[EMR7370]] (noch im entstehen) *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] *12.06.2011 [[Maschinenleuchte]] =Updates= *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit 32a47dfcab378b192e6bc4150e01f8b5367f21c9 Datei:Polizeiauto Signalanlage.jpg 6 268 693 2011-12-29T13:35:25Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Polizeiauto Scheinwerfer.jpg 6 269 694 2011-12-29T13:35:28Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Polizeiauto LED.jpg 6 270 695 2011-12-29T13:35:34Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Polizeiauto Auseinander.jpg 6 271 696 2011-12-29T13:35:36Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Polizeiauto Verpackung.jpg 6 272 697 2011-12-29T13:35:38Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Polizeiauto Ausgangszustand.jpg 6 273 698 2011-12-29T13:35:39Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Polizeiauto Abbau vorne2.jpg 6 274 699 2011-12-29T13:35:40Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Polizeiauto Abbau hinten.jpg 6 275 700 2011-12-29T13:35:44Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Polizeiauto Abbau vorne.jpg 6 276 701 2011-12-29T13:35:48Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Polizeiauto Innen.jpg 6 277 702 2011-12-29T13:35:52Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Polizeiauto Abbau hinten2.jpg 6 278 703 2011-12-29T13:35:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Polizeiauto 0 279 704 2011-12-29T13:57:27Z Chris 2 Seite erstellt wikitext text/x-wiki Mein Cousin hat - wie an anderen Stellen bereits geschrieben - eine relativ große Modellbahn. Da Weihnachten nahte und ich ihm etwas Passendes schenken wollte, setzte ich mir in den Kopf, ein standesgemäßes Polizeiauto zu bauen. =Das Auto= Damit der Polizeiwagen zu den örtlichen Gegebenheiten passt, muss es natürlich ein bayerisches sein. Obwohl ich in Ulm (von boarischer Seite aus gesehen Ausland) einkaufen ging, bekam ich einen 5er BMW mit grün-silberner Kriegsbemalung: [[Datei:Polizeiauto Ausgangszustand.jpg|thumb|Mein erster 5er BMW]] Leider konnten die mir in der Drogerie nicht sagen, ob man das Auto ohne Beschädigung auseinanderbauen kann, also musste der Versuch Klarheit schaffen. Durch leichtes Aufbiegen des Gehäuses konnte ich die Bodenplatte leicht herausziehen, was schlussendlich aber wahrscheinlich zum Brechen des Modells geführt hätte. Allerdings tat sich an andere Stelle etwas: der Lufteinlass unter dem Kühlergrill rutschte leicht heraus. Ganz herausgenommen hängt schon einmal der vordere Teil des Innenlebens heraus. Nach ein bisschen Wackeln traten die Rückleuchten heraus – der nächste Angriffspunkt. Diese entfernt, kam der vollständige Innenteil entgegen. Hier das Ganze nochmal in Bildern: <gallery> Datei:Polizeiauto Abbau vorne.jpg| Datei:Polizeiauto Abbau vorne2.jpg| Datei:Polizeiauto Abbau hinten.jpg| Datei:Polizeiauto Abbau hinten2.jpg| Datei:Polizeiauto Auseinander.jpg| </gallery> =Beleuchtung= Nun kommt der schwierigere Teil. Um der Wirklichkeit nahe zu kommen, braucht man natürlich originalgetreue Beleuchtung. Vorne weiß, hinten rot und oben blau. Blinker habe ich aus Platzmangel außen vor gelassen. Jeder, der schon einmal ein Modellauto in 1:87 in der Hand hatte, wird verstehen… Als hätte man es beim Hersteller geahnt – die Frontscheinwerfer und Rücklichter sind transparent und wie Lichtleiter nach ihnen geführt. Das erspart gröberen Dremel-Einsatz. ==Abblendlicht== [[Datei:Polizeiauto LED.jpg|thumb|Bedrahtete LED]] Beim Abblendlicht kommen zwei bläulich-weiße 0805-LEDs (oder zumindest eine merkwürdige Zwischengröße) zum Einsatz. Die Farbe erklärt sich daraus, da ich diese Leuchtdioden gerade auf Lager hatte und das leicht bläuliche Licht schon sehr nach Xenon-Scheinwerfern aussieht. Diese werden jeweils mit Fädeldraht (0,2mm) bestückt und direkt an die Lichtleiter geklebt. Erwähnenswert ist an dieser Stelle vielleicht der Kleber: Sekundenkleber ist ungeeignet, da er das Kunststoffgehäuse anlöst und somit das Licht verfälscht oder zumindest komische Spuren hinterlässt. Heißkleber löst zwar nichts an, ist für diese Anwendung (meiner Meinung) zu grobschlächtig und dürfte nicht allzu gut halten. Die Wahl fiel schließlich (da ich keinen Modellbaukleber da hatte) auf 2-Komponenten-Kleber. Dieser ist halbwegs Kunststoffverträglich und dünnflüssig genug, um nicht aufzufallen. Einzig hinderlich, ist die relativ lange Verarbeitungszeit (obwohl es ein schnellhärtender war): Über 5 Minuten hinweg eine LED an dünnen Anschlussdrähten ruhig zu halten, kann sich als durchaus schwierig erweisen. Ist aber machbar. <gallery> Datei:Polizeiauto Scheinwerfer.jpg|Ausleuchtung der Scheinwerfer </gallery> ==Rücklicht== Da mir das rumpanschen mit 2-K-Kleber meistens zu blöd ist, wurden die zwei in Reihe geschalteten Rücklicht-LEDs (ebenfalls im 0805-Gehäuse) einfach mit Sekundenkleber befestigt. Schon bevor sie Kontakt zum Gehäuse hatten, sah man die Eintrübung. Zusätzlich – und zu allem Überfluss – ging ein Rinnsal dieses verdammten Klebers nach unten zwischen Innenleben und Bodenplatte. Also mussten die beiden Teile mit sanfter Gewalt wieder getrennt und saubergeschliffen werden. Die leichten matten Überreste dieses Teufelszeugs wird man wohl nie wieder los. Wie auch immer, die Positionierung der LEDs an dieser Stelle ist relativ einfach. Da die Rückleuchten gesteckt sind, müssen auf der gegenüberliegenden Seite Löcher sein. Etwa 4mm hinter diesen befindet sich eine zweite Wandung des Innenlebens. Ideal also um die Leuchtdioden zu befestigen und auszurichten – auch wenn es in meinem Fall nicht allzu präzise war. ==Signalanlage== Ein ganz besonderes Augenmerk an einem Behördenfahrzeug ist natürlich die Sondersignalanlage auf dem Dach. Mit abermals sanfter Gewalt lässt sich diese einfach nach oben abziehen/wegreißen. Ich habe zwar schon fest damit gerechnet, spätestens hier fräsen zu müssen, allerdings konnte der Hersteller entweder einige Centbruchteile sparen oder er hat an den Innenausbau gedacht: <gallery> Datei:Polizeiauto Signalanlage.jpg|Signalanlage mit LEDs Datei:Polizeiauto Innen.jpg|Unspektakulärer Blick von innen </gallery> In den Schlitz der Signalanlage kann man 0603-LEDs pressen welche ich, wie die anderen, mit Fädeldraht vorbereitet hatte. Übrigens kann man solch kleine Bauteile am ehesten „an der frischen Luft“ bedrahten, wenn man sie auf den Rücken gelegt mit doppelseitigem Klebeband fixiert. Auf diese Weise habe ich bereits mehrfach erfolgreich 0402er-Bauteile (1x0,5mm) mit Drähtchen belötet. Entgegen weitläufiger Annahme reicht hierfür eine vergleichsweise dicke Lötspitze (Wie auch an anderen Stellen: Nicht die Größe, sondern die Technik zählt). ==Zusammenbau== Nicht zu unterschätzen ist natürlich auch das Zusammenbauen des Autos. Auf irgendeine Art und Weise müssen die Leitungen zu den LEDs zugänglich sein. Anfangs wollte ich den verwendeten Mikrocontroller mit ins Auto bauen, da dann aber noch ein Feature hinzukam und nachträgliche Firmware-Updates möglich sein sollten, hätte ich 6 Drähte herausführen müssen. Die Beleuchtung alleine hängt (mit gemeinsamer Masse) an nur 4. Da nimmt man als Stromer doch eher den Weg des geringsten Widerstandes. =Effekte= Natürlich soll die Signalanlage auch dem großen Vorbild entsprechen und originalgetreu blitzen. Auch wäre es schön, wenn man die Beleuchtung ein- und ausschalten könnte – und was macht ein Polizeiauto zu einem richtigen Polizeiauto? Ganz klar: die Sirene! Außerdem wäre kein Projekt von mir nicht ohne mindestens einen Mikrocontroller vollständig ;) ==Beleuchtung== Das Schalten der Beleuchtung könnte man zur Not auch über einen normalen Schalter übernehmen. Da die Modellanlage aber zentral über einen Kleincomputer gesteuert wird, soll alles dafür zumindest vorbereitet sein. ==Signalanlage== Das Blitzen ist – dank meiner bereits vorhandenen, aber hier noch nicht dokumentierten Timing-Engine – zumindest programmiertechnisch kein Problem. Aber in welchem Muster blitzt die Beleuchtung? Zwar gibt es in der Röhre reichlich Videomaterial von Signalanlagen, allerdings ist dieses für diesen Anwendungszweck unbrauchbar, da man aufgrund der Bildwiederholrate nur Teile des eigentlichen Blitzens mitbekommt. Ich habe schon mit dem Gedanken gespielt, bei der örtlichen Polizei zu fragen, ob ich direkt an einer Streife messen kann. Allerdings ging es noch einen Schritt einfacher: Mein Vater ist Mitglied in der hiesigen Feuerwehr und mit dem Kommandanten gut befreundet. Nachdem die Feuerwehr seit letztem Jahr ein neues Einsatzfahrzeug hat, verfügt dieses auch über eine moderne Sondersignalanlage. Ausgestattet mit einer kleinen Solarzelle, Oszilloskop und Block konnte ich die Signale hinten und auf dem Dach ausmessen. Für das „moderne“ Blitzen ergeben sich folgende Zeiten: {| class="wikitable" |- | An || 64,4ms |- | Aus || 15,2ms |- | An || 25,6ms |- | Aus || 15,2ms |- | An || 25,2ms |- | Aus || 15,2ms |- | An || 146,0ms |- | Aus || 188,0ms |} Bei dem altbekannten Muster, das ich bis jetzt nur als Doppelblitzen kannte, sind in Wirklichkeit 4 Blitze versteckt – sofern mich meine Messtechnik nicht belügt: {| class="wikitable" |- | An || 10ms |- | Aus || 35ms |- | An || 10ms |- | Aus || 85ms |- | An || 10ms |- | Aus || 35ms |- | An || 10ms |- | Aus || 350ms |} Eingefüttert in die Timing-Engine kommt etwas schon sehr brauchbares heraus. Der Kenner weiß allerdings: die beiden Signalleuchten arbeiten immer im Duo, aber nicht synchron. Da ich nur an einer Leuchte messen konnte, probierte ich beim Zeitversatz zwischen den beiden Kanälen einfach ein wenig aus. Ein Versatz von 4 Zeitschlitzen sieht gut aus und wir verwendet. Auffallend ist auch, dass die beiden Blitzformen jeweils mit 8 Zeitschlitzen abgebildet werden, die auch recht gut in ein 5ms-Raster passen. Zufall? Around the Interwebs konnte ich übrigens lediglich bei [http://www.digital-bahn.de/bau_pkw/pkw.htm Digital-Bahn.de] etwas zum Timing der Signalanlagen finden. Leider erst nachdem ich es selbst herausgefunden habe. ==Sirene== Neben dem Lichterspiel braucht ein Polizeiauto natürlich auch eine Sirene. Nach ein einer kurzen Suche wurde ich auch [http://www.youtube.com/watch?v=dcgiTFHMMAw fündig]. Da ich für die recht einfache Tonfolge keine SD-Karte verbraten wollte, musste alles in einen AVR passen. Verwendet wird, wie bei Marvin (Link!) ein ATtiny45, der genug Platz bieten sollte. Mit ein wenig Audiobearbeitung konnte ich Audioschnipsel herausnehmen, die für Loops verwendet werden können. Verhängnisvoll ist hier die Schwebung, die die Sirene nach Sirene anhören lässt. ;) Aber es geht natürlich auch mathematischer ;) Dazu habe ich mir über einen der Töne eine Spektralanalyse machen lassen und mir über Excel die am stärksten vertretenen Spektralanteile anzeigen lassen. Zurück in Matlab habe ich mir ein kleines M-File geschrieben, dass aus Frequenzen und Leistungen eine Waveform erzeugt und auch gleich als .wav speichert. Nebenbei wird Wellenform und Spektrum auf dem Bildschirm ausgegeben: (M-File) Leider half auch das Verwenden der 30 stärksten Spektrallinien nicht, den Ton richtig zu rekonstruieren. Es hörte sich immer sehr blechern an. Nachdem die beiden Loops etwas angepasst (Normalisierung, Verschieben Anfangs- & Endamplituden und Downsampling) ging es daran, diese in Code zu verpacken. Da es in Matlab sehr einfach ist, Wave-Dateien zu verarbeiten, lud ich sie, passte den Pegel auf den Wertebereich 0-255 an und erzeugte daraus eine C-Header-Datei. Mit etwa 2000 Byte sind die Audiodaten im durchaus überschaubaren Bereich. Auf dem Mikrocontroller werden sie per Pulsweitenmodulation ausgegeben. Dafür wird, wie beim [http://elm-chan.org/works/sd8p/report.html Simple SD Audio Player] von ChaN die interne PLL verwendet, um eine PWM-Frequenz im nicht-hörbaren Bereich zu verwenden. Zur Ausgabe werden beide Timer benötigt – der eine macht PWM, der andere das Sampling mit etwa 11kHz. Die Frequenzabweichung zur korrekten Samplingfrequenz merkt man nicht, da sind die Verzerrungen durch die niedrige Samplingrate und dem 8-Bit-Sound deutlich stärker. Die Verwendung beider Timer für die Soundausgabe führt allerdings zu dem Problem, dass für das Blitzen keine direkte Zeitbasis mehr zur Verfügung steht. Abhilfe schafft ein kleiner Postscaler für den Timer, der nach Ablauf von ca. 5ms ein Flag in einer Variable setzt. Dieses wird in der Endlosschleife im Hauptprogramm ausgewertet und die Timing-Engine bedient. Zum Treiben des Lautsprechers wird ein einfacher B-Verstärker verwendet, der direkt mit dem Signal aus dem AVR angesteuert wird. Dahinter ein Kondensator zum Entkoppeln von Gleichströmen und ein Lautsprecher. Der Sound reißt zwar keine Wände ein, ist aber durchaus akzeptabel. ==Steuerung== Immer nur Tatütata und volle Beleuchtung ist natürlich langweilig wenn nicht sogar nervig. Da am AVR noch ein Pin (abgesehen vom Reset) frei ist, bietet sich dieser natürlich an. Um das Modellauto direkt einsetzen zu können (ich habe nichts zum Simulieren der Modellbahnsteuerung hier), muss man über die eine Leitung möglichst diskret 4 verschiedene Elemente steuern – macht 16 Zustände. Da der ATtiny45 einen AD-Wandler besitzt, war die Verwendung natürlich naheliegend, was auch wunderbar funktioniert. Einzig die Stellungen des Potis muss man sich merken. =Geschenkverpackung= Damit ich das Auto auch vernünftig schenken konnte, kam die Elektronik in eine etwas ansprechende Weihnachtsverpackung. Mit einem Schalter an der Rückseite konnte man Beleuchtung und Sound einschalten: <gallery> Bild:Polizeiauto Verpackung.jpg| </gallery> Und es kam sehr gut an! Keine Stunde nach dem Schenken war das Auto auf der Anlage verbaut. [[Kategorie:Modellbau]] 5c42a6ee5dea03391e6a870a53766758081b3044 707 704 2011-12-29T14:24:24Z Chris 2 Download, Stromlaufplan und AVR-Infobox hinzugefügt wikitext text/x-wiki Mein Cousin hat - wie an anderen Stellen bereits geschrieben - eine relativ große Modellbahn. Da Weihnachten nahte und ich ihm etwas Passendes schenken wollte, setzte ich mir in den Kopf, ein standesgemäßes Polizeiauto zu bauen. =Das Auto= [[Datei:Polizeiauto Ausgangszustand.jpg|thumb|Mein erster 5er BMW]] Damit der Polizeiwagen zu den örtlichen Gegebenheiten passt, muss es natürlich ein bayerisches sein. Obwohl ich in Ulm (von boarischer Seite aus gesehen Ausland) einkaufen ging, bekam ich einen 5er BMW mit grün-silberner Kriegsbemalung: Leider konnten die mir in der Drogerie nicht sagen, ob man das Auto ohne Beschädigung auseinanderbauen kann, also musste der Versuch Klarheit schaffen. Durch leichtes Aufbiegen des Gehäuses konnte ich die Bodenplatte leicht herausziehen, was schlussendlich aber wahrscheinlich zum Brechen des Modells geführt hätte. Allerdings tat sich an andere Stelle etwas: der Lufteinlass unter dem Kühlergrill rutschte leicht heraus. Ganz herausgenommen hängt schon einmal der vordere Teil des Innenlebens heraus. Nach ein bisschen Wackeln traten die Rückleuchten heraus – der nächste Angriffspunkt. Diese entfernt, kam der vollständige Innenteil entgegen. Hier das Ganze nochmal in Bildern: <gallery> Datei:Polizeiauto Abbau vorne.jpg| Datei:Polizeiauto Abbau vorne2.jpg| Datei:Polizeiauto Abbau hinten.jpg| Datei:Polizeiauto Abbau hinten2.jpg| Datei:Polizeiauto Auseinander.jpg| </gallery> =Beleuchtung= Nun kommt der schwierigere Teil. Um der Wirklichkeit nahe zu kommen, braucht man natürlich originalgetreue Beleuchtung. Vorne weiß, hinten rot und oben blau. Blinker habe ich aus Platzmangel außen vor gelassen. Jeder, der schon einmal ein Modellauto in 1:87 in der Hand hatte, wird verstehen… Als hätte man es beim Hersteller geahnt – die Frontscheinwerfer und Rücklichter sind transparent und wie Lichtleiter nach ihnen geführt. Das erspart gröberen Dremel-Einsatz. ==Abblendlicht== [[Datei:Polizeiauto LED.jpg|thumb|Bedrahtete LED]] Beim Abblendlicht kommen zwei bläulich-weiße 0805-LEDs (oder zumindest eine merkwürdige Zwischengröße) zum Einsatz. Die Farbe erklärt sich daraus, da ich diese Leuchtdioden gerade auf Lager hatte und das leicht bläuliche Licht schon sehr nach Xenon-Scheinwerfern aussieht. Diese werden jeweils mit Fädeldraht (0,2mm) bestückt und direkt an die Lichtleiter geklebt. Erwähnenswert ist an dieser Stelle vielleicht der Kleber: Sekundenkleber ist ungeeignet, da er das Kunststoffgehäuse anlöst und somit das Licht verfälscht oder zumindest komische Spuren hinterlässt. Heißkleber löst zwar nichts an, ist für diese Anwendung (meiner Meinung) zu grobschlächtig und dürfte nicht allzu gut halten. Die Wahl fiel schließlich (da ich keinen Modellbaukleber da hatte) auf 2-Komponenten-Kleber. Dieser ist halbwegs Kunststoffverträglich und dünnflüssig genug, um nicht aufzufallen. Einzig hinderlich, ist die relativ lange Verarbeitungszeit (obwohl es ein schnellhärtender war): Über 5 Minuten hinweg eine LED an dünnen Anschlussdrähten ruhig zu halten, kann sich als durchaus schwierig erweisen. Ist aber machbar. <gallery> Datei:Polizeiauto Scheinwerfer.jpg|Ausleuchtung der Scheinwerfer </gallery> ==Rücklicht== Da mir das rumpanschen mit 2-K-Kleber meistens zu blöd ist, wurden die zwei in Reihe geschalteten Rücklicht-LEDs (ebenfalls im 0805-Gehäuse) einfach mit Sekundenkleber befestigt. Schon bevor sie Kontakt zum Gehäuse hatten, sah man die Eintrübung. Zusätzlich – und zu allem Überfluss – ging ein Rinnsal dieses verdammten Klebers nach unten zwischen Innenleben und Bodenplatte. Also mussten die beiden Teile mit sanfter Gewalt wieder getrennt und saubergeschliffen werden. Die leichten matten Überreste dieses Teufelszeugs wird man wohl nie wieder los. Wie auch immer, die Positionierung der LEDs an dieser Stelle ist relativ einfach. Da die Rückleuchten gesteckt sind, müssen auf der gegenüberliegenden Seite Löcher sein. Etwa 4mm hinter diesen befindet sich eine zweite Wandung des Innenlebens. Ideal also um die Leuchtdioden zu befestigen und auszurichten – auch wenn es in meinem Fall nicht allzu präzise war. ==Signalanlage== Ein ganz besonderes Augenmerk an einem Behördenfahrzeug ist natürlich die Sondersignalanlage auf dem Dach. Mit abermals sanfter Gewalt lässt sich diese einfach nach oben abziehen/wegreißen. Ich habe zwar schon fest damit gerechnet, spätestens hier fräsen zu müssen, allerdings konnte der Hersteller entweder einige Centbruchteile sparen oder er hat an den Innenausbau gedacht: <gallery> Datei:Polizeiauto Signalanlage.jpg|Signalanlage mit LEDs Datei:Polizeiauto Innen.jpg|Unspektakulärer Blick von innen </gallery> In den Schlitz der Signalanlage kann man 0603-LEDs pressen welche ich, wie die anderen, mit Fädeldraht vorbereitet hatte. Übrigens kann man solch kleine Bauteile am ehesten „an der frischen Luft“ bedrahten, wenn man sie auf den Rücken gelegt mit doppelseitigem Klebeband fixiert. Auf diese Weise habe ich bereits mehrfach erfolgreich 0402er-Bauteile (1x0,5mm) mit Drähtchen belötet. Entgegen weitläufiger Annahme reicht hierfür eine vergleichsweise dicke Lötspitze (Wie auch an anderen Stellen: Nicht die Größe, sondern die Technik zählt). ==Zusammenbau== Nicht zu unterschätzen ist natürlich auch das Zusammenbauen des Autos. Auf irgendeine Art und Weise müssen die Leitungen zu den LEDs zugänglich sein. Anfangs wollte ich den verwendeten Mikrocontroller mit ins Auto bauen, da dann aber noch ein Feature hinzukam und nachträgliche Firmware-Updates möglich sein sollten, hätte ich 6 Drähte herausführen müssen. Die Beleuchtung alleine hängt (mit gemeinsamer Masse) an nur 4. Da nimmt man als Stromer doch eher den Weg des geringsten Widerstandes. =Effekte= Natürlich soll die Signalanlage auch dem großen Vorbild entsprechen und originalgetreu blitzen. Auch wäre es schön, wenn man die Beleuchtung ein- und ausschalten könnte – und was macht ein Polizeiauto zu einem richtigen Polizeiauto? Ganz klar: die Sirene! Außerdem wäre kein Projekt von mir nicht ohne mindestens einen Mikrocontroller vollständig ;) ==Beleuchtung== Das Schalten der Beleuchtung könnte man zur Not auch über einen normalen Schalter übernehmen. Da die Modellanlage aber zentral über einen Kleincomputer gesteuert wird, soll alles dafür zumindest vorbereitet sein. ==Signalanlage== Das Blitzen ist – dank meiner bereits vorhandenen, aber hier noch nicht dokumentierten Timing-Engine – zumindest programmiertechnisch kein Problem. Aber in welchem Muster blitzt die Beleuchtung? Zwar gibt es in der Röhre reichlich Videomaterial von Signalanlagen, allerdings ist dieses für diesen Anwendungszweck unbrauchbar, da man aufgrund der Bildwiederholrate nur Teile des eigentlichen Blitzens mitbekommt. Ich habe schon mit dem Gedanken gespielt, bei der örtlichen Polizei zu fragen, ob ich direkt an einer Streife messen kann. Allerdings ging es noch einen Schritt einfacher: Mein Vater ist Mitglied in der hiesigen Feuerwehr und mit dem Kommandanten gut befreundet. Nachdem die Feuerwehr seit letztem Jahr ein neues Einsatzfahrzeug hat, verfügt dieses auch über eine moderne Sondersignalanlage. Ausgestattet mit einer kleinen Solarzelle, Oszilloskop und Block konnte ich die Signale hinten und auf dem Dach ausmessen. Für das „moderne“ Blitzen ergeben sich folgende Zeiten: {| class="wikitable" |- | An || 64,4ms |- | Aus || 15,2ms |- | An || 25,6ms |- | Aus || 15,2ms |- | An || 25,2ms |- | Aus || 15,2ms |- | An || 146,0ms |- | Aus || 188,0ms |} Bei dem altbekannten Muster, das ich bis jetzt nur als Doppelblitzen kannte, sind in Wirklichkeit 4 Blitze versteckt – sofern mich meine Messtechnik nicht belügt: {| class="wikitable" |- | An || 10ms |- | Aus || 35ms |- | An || 10ms |- | Aus || 85ms |- | An || 10ms |- | Aus || 35ms |- | An || 10ms |- | Aus || 350ms |} Eingefüttert in die Timing-Engine kommt etwas schon sehr brauchbares heraus. Der Kenner weiß allerdings: die beiden Signalleuchten arbeiten immer im Duo, aber nicht synchron. Da ich nur an einer Leuchte messen konnte, probierte ich beim Zeitversatz zwischen den beiden Kanälen einfach ein wenig aus. Ein Versatz von 4 Zeitschlitzen sieht gut aus und wir verwendet. Auffallend ist auch, dass die beiden Blitzformen jeweils mit 8 Zeitschlitzen abgebildet werden, die auch recht gut in ein 5ms-Raster passen. Zufall? Around the Interwebs konnte ich übrigens lediglich bei [http://www.digital-bahn.de/bau_pkw/pkw.htm Digital-Bahn.de] etwas zum Timing der Signalanlagen finden. Leider erst nachdem ich es selbst herausgefunden habe. ==Sirene== Neben dem Lichterspiel braucht ein Polizeiauto natürlich auch eine Sirene. Nach ein einer kurzen Suche wurde ich auch [http://www.youtube.com/watch?v=dcgiTFHMMAw fündig]. Da ich für die recht einfache Tonfolge keine SD-Karte verbraten wollte, musste alles in einen AVR passen. Verwendet wird, wie bei Marvin (Link!) ein ATtiny45, der genug Platz bieten sollte. Mit ein wenig Audiobearbeitung konnte ich Audioschnipsel herausnehmen, die für Loops verwendet werden können. Verhängnisvoll ist hier die Schwebung, die die Sirene nach Sirene anhören lässt. ;) Aber es geht natürlich auch mathematischer ;) Dazu habe ich mir über einen der Töne eine Spektralanalyse machen lassen und mir über Excel die am stärksten vertretenen Spektralanteile anzeigen lassen. Zurück in Matlab habe ich mir ein kleines M-File geschrieben, dass aus Frequenzen und Leistungen eine Waveform erzeugt und auch gleich als .wav speichert. Nebenbei wird Wellenform und Spektrum auf dem Bildschirm ausgegeben. Leider half auch das Verwenden der 30 stärksten Spektrallinien nicht, den Ton richtig zu rekonstruieren. Es hörte sich immer sehr blechern an. Nachdem die beiden Loops etwas angepasst (Normalisierung, Verschieben Anfangs- & Endamplituden und Downsampling) ging es daran, diese in Code zu verpacken. Da es in Matlab sehr einfach ist, Wave-Dateien zu verarbeiten, lud ich sie, passte den Pegel auf den Wertebereich 0-255 an und erzeugte daraus eine C-Header-Datei. Mit etwa 2000 Byte sind die Audiodaten im durchaus überschaubaren Bereich. Auf dem Mikrocontroller werden sie per Pulsweitenmodulation ausgegeben. Dafür wird, wie beim [http://elm-chan.org/works/sd8p/report.html Simple SD Audio Player] von ChaN die interne PLL verwendet, um eine PWM-Frequenz im nicht-hörbaren Bereich zu verwenden. Zur Ausgabe werden beide Timer benötigt – der eine macht PWM, der andere das Sampling mit etwa 11kHz. Die Frequenzabweichung zur korrekten Samplingfrequenz merkt man nicht, da sind die Verzerrungen durch die niedrige Samplingrate und dem 8-Bit-Sound deutlich stärker. Die Verwendung beider Timer für die Soundausgabe führt allerdings zu dem Problem, dass für das Blitzen keine direkte Zeitbasis mehr zur Verfügung steht. Abhilfe schafft ein kleiner Postscaler für den Timer, der nach Ablauf von ca. 5ms ein Flag in einer Variable setzt. Dieses wird in der Endlosschleife im Hauptprogramm ausgewertet und die Timing-Engine bedient. Zum Treiben des Lautsprechers wird ein einfacher B-Verstärker verwendet, der direkt mit dem Signal aus dem AVR angesteuert wird. Dahinter ein Kondensator zum Entkoppeln von Gleichströmen und ein Lautsprecher. Der Sound reißt zwar keine Wände ein, ist aber durchaus akzeptabel. ==Steuerung== [[Datei:Polizeiauto Stromlaufplan.png|thumb]] {{Infobox AVR | Typ = ATtiny45 | Takt = 16 | FuseH = DD | FuseL = E1 | FuseE = FF }} Immer nur Tatütata und volle Beleuchtung ist natürlich langweilig wenn nicht sogar nervig. Da am AVR noch ein Pin (abgesehen vom Reset) frei ist, bietet sich dieser natürlich an. Um das Modellauto direkt einsetzen zu können (ich habe nichts zum Simulieren der Modellbahnsteuerung hier), muss man über die eine Leitung möglichst diskret 4 verschiedene Elemente steuern – macht 16 Zustände. Da der ATtiny45 einen AD-Wandler besitzt, war die Verwendung natürlich naheliegend, was auch wunderbar funktioniert. Einzig die Stellungen des Potis muss man sich merken. =Geschenkverpackung= Damit ich das Auto auch vernünftig schenken konnte, kam die Elektronik in eine etwas ansprechende Weihnachtsverpackung. Mit einem Schalter an der Rückseite konnte man Beleuchtung und Sound einschalten: <gallery> Bild:Polizeiauto Verpackung.jpg| </gallery> Und es kam sehr gut an! Keine Stunde nach dem Schenken war das Auto auf der Anlage verbaut. =Download= M-File, Stromlaufplan, Sounds und Quelltexte: [[Datei:Polizeiauto.zip]] [[Kategorie:Modellbau]] a4203a4a5db26426924e6371afda0b119f682423 710 707 2012-03-08T21:00:22Z Chris 2 Video hinzugefügt wikitext text/x-wiki Mein Cousin hat - wie an anderen Stellen bereits geschrieben - eine relativ große Modellbahn. Da Weihnachten nahte und ich ihm etwas Passendes schenken wollte, setzte ich mir in den Kopf, ein standesgemäßes Polizeiauto zu bauen. =Das Auto= [[Datei:Polizeiauto Ausgangszustand.jpg|thumb|Mein erster 5er BMW]] Damit der Polizeiwagen zu den örtlichen Gegebenheiten passt, muss es natürlich ein bayerisches sein. Obwohl ich in Ulm (von boarischer Seite aus gesehen Ausland) einkaufen ging, bekam ich einen 5er BMW mit grün-silberner Kriegsbemalung: Leider konnten die mir in der Drogerie nicht sagen, ob man das Auto ohne Beschädigung auseinanderbauen kann, also musste der Versuch Klarheit schaffen. Durch leichtes Aufbiegen des Gehäuses konnte ich die Bodenplatte leicht herausziehen, was schlussendlich aber wahrscheinlich zum Brechen des Modells geführt hätte. Allerdings tat sich an andere Stelle etwas: der Lufteinlass unter dem Kühlergrill rutschte leicht heraus. Ganz herausgenommen hängt schon einmal der vordere Teil des Innenlebens heraus. Nach ein bisschen Wackeln traten die Rückleuchten heraus – der nächste Angriffspunkt. Diese entfernt, kam der vollständige Innenteil entgegen. Hier das Ganze nochmal in Bildern: <gallery> Datei:Polizeiauto Abbau vorne.jpg| Datei:Polizeiauto Abbau vorne2.jpg| Datei:Polizeiauto Abbau hinten.jpg| Datei:Polizeiauto Abbau hinten2.jpg| Datei:Polizeiauto Auseinander.jpg| </gallery> =Beleuchtung= Nun kommt der schwierigere Teil. Um der Wirklichkeit nahe zu kommen, braucht man natürlich originalgetreue Beleuchtung. Vorne weiß, hinten rot und oben blau. Blinker habe ich aus Platzmangel außen vor gelassen. Jeder, der schon einmal ein Modellauto in 1:87 in der Hand hatte, wird verstehen… Als hätte man es beim Hersteller geahnt – die Frontscheinwerfer und Rücklichter sind transparent und wie Lichtleiter nach ihnen geführt. Das erspart gröberen Dremel-Einsatz. ==Abblendlicht== [[Datei:Polizeiauto LED.jpg|thumb|Bedrahtete LED]] Beim Abblendlicht kommen zwei bläulich-weiße 0805-LEDs (oder zumindest eine merkwürdige Zwischengröße) zum Einsatz. Die Farbe erklärt sich daraus, da ich diese Leuchtdioden gerade auf Lager hatte und das leicht bläuliche Licht schon sehr nach Xenon-Scheinwerfern aussieht. Diese werden jeweils mit Fädeldraht (0,2mm) bestückt und direkt an die Lichtleiter geklebt. Erwähnenswert ist an dieser Stelle vielleicht der Kleber: Sekundenkleber ist ungeeignet, da er das Kunststoffgehäuse anlöst und somit das Licht verfälscht oder zumindest komische Spuren hinterlässt. Heißkleber löst zwar nichts an, ist für diese Anwendung (meiner Meinung) zu grobschlächtig und dürfte nicht allzu gut halten. Die Wahl fiel schließlich (da ich keinen Modellbaukleber da hatte) auf 2-Komponenten-Kleber. Dieser ist halbwegs Kunststoffverträglich und dünnflüssig genug, um nicht aufzufallen. Einzig hinderlich, ist die relativ lange Verarbeitungszeit (obwohl es ein schnellhärtender war): Über 5 Minuten hinweg eine LED an dünnen Anschlussdrähten ruhig zu halten, kann sich als durchaus schwierig erweisen. Ist aber machbar. <gallery> Datei:Polizeiauto Scheinwerfer.jpg|Ausleuchtung der Scheinwerfer </gallery> ==Rücklicht== Da mir das rumpanschen mit 2-K-Kleber meistens zu blöd ist, wurden die zwei in Reihe geschalteten Rücklicht-LEDs (ebenfalls im 0805-Gehäuse) einfach mit Sekundenkleber befestigt. Schon bevor sie Kontakt zum Gehäuse hatten, sah man die Eintrübung. Zusätzlich – und zu allem Überfluss – ging ein Rinnsal dieses verdammten Klebers nach unten zwischen Innenleben und Bodenplatte. Also mussten die beiden Teile mit sanfter Gewalt wieder getrennt und saubergeschliffen werden. Die leichten matten Überreste dieses Teufelszeugs wird man wohl nie wieder los. Wie auch immer, die Positionierung der LEDs an dieser Stelle ist relativ einfach. Da die Rückleuchten gesteckt sind, müssen auf der gegenüberliegenden Seite Löcher sein. Etwa 4mm hinter diesen befindet sich eine zweite Wandung des Innenlebens. Ideal also um die Leuchtdioden zu befestigen und auszurichten – auch wenn es in meinem Fall nicht allzu präzise war. ==Signalanlage== Ein ganz besonderes Augenmerk an einem Behördenfahrzeug ist natürlich die Sondersignalanlage auf dem Dach. Mit abermals sanfter Gewalt lässt sich diese einfach nach oben abziehen/wegreißen. Ich habe zwar schon fest damit gerechnet, spätestens hier fräsen zu müssen, allerdings konnte der Hersteller entweder einige Centbruchteile sparen oder er hat an den Innenausbau gedacht: <gallery> Datei:Polizeiauto Signalanlage.jpg|Signalanlage mit LEDs Datei:Polizeiauto Innen.jpg|Unspektakulärer Blick von innen </gallery> In den Schlitz der Signalanlage kann man 0603-LEDs pressen welche ich, wie die anderen, mit Fädeldraht vorbereitet hatte. Übrigens kann man solch kleine Bauteile am ehesten „an der frischen Luft“ bedrahten, wenn man sie auf den Rücken gelegt mit doppelseitigem Klebeband fixiert. Auf diese Weise habe ich bereits mehrfach erfolgreich 0402er-Bauteile (1x0,5mm) mit Drähtchen belötet. Entgegen weitläufiger Annahme reicht hierfür eine vergleichsweise dicke Lötspitze (Wie auch an anderen Stellen: Nicht die Größe, sondern die Technik zählt). ==Zusammenbau== Nicht zu unterschätzen ist natürlich auch das Zusammenbauen des Autos. Auf irgendeine Art und Weise müssen die Leitungen zu den LEDs zugänglich sein. Anfangs wollte ich den verwendeten Mikrocontroller mit ins Auto bauen, da dann aber noch ein Feature hinzukam und nachträgliche Firmware-Updates möglich sein sollten, hätte ich 6 Drähte herausführen müssen. Die Beleuchtung alleine hängt (mit gemeinsamer Masse) an nur 4. Da nimmt man als Stromer doch eher den Weg des geringsten Widerstandes. =Effekte= Natürlich soll die Signalanlage auch dem großen Vorbild entsprechen und originalgetreu blitzen. Auch wäre es schön, wenn man die Beleuchtung ein- und ausschalten könnte – und was macht ein Polizeiauto zu einem richtigen Polizeiauto? Ganz klar: die Sirene! Außerdem wäre kein Projekt von mir nicht ohne mindestens einen Mikrocontroller vollständig ;) ==Beleuchtung== Das Schalten der Beleuchtung könnte man zur Not auch über einen normalen Schalter übernehmen. Da die Modellanlage aber zentral über einen Kleincomputer gesteuert wird, soll alles dafür zumindest vorbereitet sein. ==Signalanlage== Das Blitzen ist – dank meiner bereits vorhandenen, aber hier noch nicht dokumentierten Timing-Engine – zumindest programmiertechnisch kein Problem. Aber in welchem Muster blitzt die Beleuchtung? Zwar gibt es in der Röhre reichlich Videomaterial von Signalanlagen, allerdings ist dieses für diesen Anwendungszweck unbrauchbar, da man aufgrund der Bildwiederholrate nur Teile des eigentlichen Blitzens mitbekommt. Ich habe schon mit dem Gedanken gespielt, bei der örtlichen Polizei zu fragen, ob ich direkt an einer Streife messen kann. Allerdings ging es noch einen Schritt einfacher: Mein Vater ist Mitglied in der hiesigen Feuerwehr und mit dem Kommandanten gut befreundet. Nachdem die Feuerwehr seit letztem Jahr ein neues Einsatzfahrzeug hat, verfügt dieses auch über eine moderne Sondersignalanlage. Ausgestattet mit einer kleinen Solarzelle, Oszilloskop und Block konnte ich die Signale hinten und auf dem Dach ausmessen. Für das „moderne“ Blitzen ergeben sich folgende Zeiten: {| class="wikitable" |- | An || 64,4ms |- | Aus || 15,2ms |- | An || 25,6ms |- | Aus || 15,2ms |- | An || 25,2ms |- | Aus || 15,2ms |- | An || 146,0ms |- | Aus || 188,0ms |} Bei dem altbekannten Muster, das ich bis jetzt nur als Doppelblitzen kannte, sind in Wirklichkeit 4 Blitze versteckt – sofern mich meine Messtechnik nicht belügt: {| class="wikitable" |- | An || 10ms |- | Aus || 35ms |- | An || 10ms |- | Aus || 85ms |- | An || 10ms |- | Aus || 35ms |- | An || 10ms |- | Aus || 350ms |} Eingefüttert in die Timing-Engine kommt etwas schon sehr brauchbares heraus. Der Kenner weiß allerdings: die beiden Signalleuchten arbeiten immer im Duo, aber nicht synchron. Da ich nur an einer Leuchte messen konnte, probierte ich beim Zeitversatz zwischen den beiden Kanälen einfach ein wenig aus. Ein Versatz von 4 Zeitschlitzen sieht gut aus und wir verwendet. Auffallend ist auch, dass die beiden Blitzformen jeweils mit 8 Zeitschlitzen abgebildet werden, die auch recht gut in ein 5ms-Raster passen. Zufall? Around the Interwebs konnte ich übrigens lediglich bei [http://www.digital-bahn.de/bau_pkw/pkw.htm Digital-Bahn.de] etwas zum Timing der Signalanlagen finden. Leider erst nachdem ich es selbst herausgefunden habe. ==Sirene== Neben dem Lichterspiel braucht ein Polizeiauto natürlich auch eine Sirene. Nach ein einer kurzen Suche wurde ich auch [http://www.youtube.com/watch?v=dcgiTFHMMAw fündig]. Da ich für die recht einfache Tonfolge keine SD-Karte verbraten wollte, musste alles in einen AVR passen. Verwendet wird, wie bei Marvin (Link!) ein ATtiny45, der genug Platz bieten sollte. Mit ein wenig Audiobearbeitung konnte ich Audioschnipsel herausnehmen, die für Loops verwendet werden können. Verhängnisvoll ist hier die Schwebung, die die Sirene nach Sirene anhören lässt. ;) Aber es geht natürlich auch mathematischer ;) Dazu habe ich mir über einen der Töne eine Spektralanalyse machen lassen und mir über Excel die am stärksten vertretenen Spektralanteile anzeigen lassen. Zurück in Matlab habe ich mir ein kleines M-File geschrieben, dass aus Frequenzen und Leistungen eine Waveform erzeugt und auch gleich als .wav speichert. Nebenbei wird Wellenform und Spektrum auf dem Bildschirm ausgegeben. Leider half auch das Verwenden der 30 stärksten Spektrallinien nicht, den Ton richtig zu rekonstruieren. Es hörte sich immer sehr blechern an. Nachdem die beiden Loops etwas angepasst (Normalisierung, Verschieben Anfangs- & Endamplituden und Downsampling) ging es daran, diese in Code zu verpacken. Da es in Matlab sehr einfach ist, Wave-Dateien zu verarbeiten, lud ich sie, passte den Pegel auf den Wertebereich 0-255 an und erzeugte daraus eine C-Header-Datei. Mit etwa 2000 Byte sind die Audiodaten im durchaus überschaubaren Bereich. Auf dem Mikrocontroller werden sie per Pulsweitenmodulation ausgegeben. Dafür wird, wie beim [http://elm-chan.org/works/sd8p/report.html Simple SD Audio Player] von ChaN die interne PLL verwendet, um eine PWM-Frequenz im nicht-hörbaren Bereich zu verwenden. Zur Ausgabe werden beide Timer benötigt – der eine macht PWM, der andere das Sampling mit etwa 11kHz. Die Frequenzabweichung zur korrekten Samplingfrequenz merkt man nicht, da sind die Verzerrungen durch die niedrige Samplingrate und dem 8-Bit-Sound deutlich stärker. Die Verwendung beider Timer für die Soundausgabe führt allerdings zu dem Problem, dass für das Blitzen keine direkte Zeitbasis mehr zur Verfügung steht. Abhilfe schafft ein kleiner Postscaler für den Timer, der nach Ablauf von ca. 5ms ein Flag in einer Variable setzt. Dieses wird in der Endlosschleife im Hauptprogramm ausgewertet und die Timing-Engine bedient. Zum Treiben des Lautsprechers wird ein einfacher B-Verstärker verwendet, der direkt mit dem Signal aus dem AVR angesteuert wird. Dahinter ein Kondensator zum Entkoppeln von Gleichströmen und ein Lautsprecher. Der Sound reißt zwar keine Wände ein, ist aber durchaus akzeptabel. ==Steuerung== [[Datei:Polizeiauto Stromlaufplan.png|thumb]] {{Infobox AVR | Typ = ATtiny45 | Takt = 16 | FuseH = DD | FuseL = E1 | FuseE = FF }} Immer nur Tatütata und volle Beleuchtung ist natürlich langweilig wenn nicht sogar nervig. Da am AVR noch ein Pin (abgesehen vom Reset) frei ist, bietet sich dieser natürlich an. Um das Modellauto direkt einsetzen zu können (ich habe nichts zum Simulieren der Modellbahnsteuerung hier), muss man über die eine Leitung möglichst diskret 4 verschiedene Elemente steuern – macht 16 Zustände. Da der ATtiny45 einen AD-Wandler besitzt, war die Verwendung natürlich naheliegend, was auch wunderbar funktioniert. Einzig die Stellungen des Potis muss man sich merken. =Geschenkverpackung= Damit ich das Auto auch vernünftig schenken konnte, kam die Elektronik in eine etwas ansprechende Weihnachtsverpackung. Mit einem Schalter an der Rückseite konnte man Beleuchtung und Sound einschalten: <gallery> Bild:Polizeiauto Verpackung.jpg| </gallery> Und es kam sehr gut an! Keine Stunde nach dem Schenken war das Auto auf der Anlage verbaut. =Video= Wer noch ein etwas verwackeltes und leises Video sehen möchte, kann dies gerne auf [http://www.youtube.com/watch/?v=0zPEr9iozFc Youtube] tun. =Download= M-File, Stromlaufplan, Sounds und Quelltexte: [[Datei:Polizeiauto.zip]] [[Kategorie:Modellbau]] 43988a0ed6d814b212cfd916ebc67310ac401cde Datei:Polizeiauto Stromlaufplan.png 6 280 705 2011-12-29T14:05:41Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Polizeiauto.zip 6 281 706 2011-12-29T14:17:45Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Benutzer:Chris 2 45 709 612 2012-01-15T22:33:15Z Chris 2 wikitext text/x-wiki Tjo, das ist es also, mein ganz privater Bereich auf hobbyelektronik.org. Ich bin Chris und quasi der Schöpfer dieser Homepage. = Wie es dazu kam = Irgendwann in diesem Jahrtausend (lt. Archive.org Ende 2003) fing ich damit an, meine (mehr oder weniger gelungenen) Bastel-Projekte in HTML zu verwandeln und auf hobby-elektronik.de.vu zu veröffentlichen. Der Speicherplatz bei Tripod wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich irgendwann, auf das schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10 April 2005 die Domain hobbyelektronik.org registriert. Zu .org kam es, da mir eine Woche davor jemand die .net-Domain weggeschnappte. Im Nachhinein bin ich glücklich, dem damaligen .net-Hype entgangen zu sein. Eine richtige Organisation sind wir zwar noch immer nicht aber was nicht ist, kann ja noch werden ;) = Was ich mache = Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" bezeichnen. Seit Oktober 2009 studiere ich Elektrotechnik/Nachrichtentechnik an der [http://www.hs-ulm.de Hochschule Ulm]. Die Schnittmenge bzw. vielmehr die Kombination aus den beiden Bereichen kommen auch wieder in meinen Hobbys zusammen, wobei ich Software und Elektronik an dieser Stelle gar nicht mehr trennen möchte. = Warum das Ganze? = Ganz einfach: Weil es mir Spaß macht. Wie an anderer Stelle schon erwähnt, bezeichne ich diese Seite als "nicht-kommerzielles Umfeld". Damit ist gemeint, dass ich mit dieser Homepage kein Geld verdiene (keine Werbung, keine Partnerschaften mir irgendwelchen Firmen, etc.) und es ehrlich gesagt auch nicht will. (Wer spenden will - gerne auch Sachspenden - ist natürlich willkommen ;)) Neben dem Spaß geht es mir auch darum, etwas an andere Bastler, Elektronik-Einsteiger und DICH weiter- bzw. zurückzugeben. Auch ich habe mal sehr klein angefangen und war froh um alles, was mich näher in Richtung Computer und Elektronik brachte (und auch heute noch bringt). Wenn man so will, kann man es als Kreislauf verstehen :) = Kannst du mir... = ...bei <Thema hier einsetzen> helfen? Jein. Wenn du ehrliches Interesse hast, helfe ich gerne. Was ich allerdings überhaupt nicht abkann ist die "Mach mal-" bzw. "Freibiermentalität", die manche an den Tag legen. Solche können erst wiederkommen, wenn ich einen Gewerbeschein habe... = Kontakt = Solltest du Fragen, Kritik, Verbesserungsvorschläge oder Fehler auf den Seiten hier gefunden haben - eine kleine Mail genügt und wird gerne beantwortet: chris at hobbyelektronik punkt org (siehe auch [[Hobbyelektronik.org:Impressum|Impressum]]) d34f4261381c1ba64b7caf065a297207977680f7 Energieerfassung 0 168 711 643 2012-03-11T09:09:13Z Chris 2 /* Stromzähler */ Formel (hoffentlich richtig) in TeX umgeschrieben wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== [[Datei:Nrg hauptzaehler.jpg|thumb|Stromzähler mit aufgesetzter Erfassungseinheit]] Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[:wpde:Ferraris-Zähler|Ferrais-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. [[Datei:Bananen Frucht.jpg|thumb|Eine Banane, eisenreich und sehr bekömmlich (cc:by-sa Darkone)]] Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. <gallery> Datei:Nrg zaehler umlauf.png|Ein Umlauf, wie er direkt am Fototransistor gemessen wird Datei:Nrg zaehler rauschen.png|"Grundrauschen" der rotierenden Scheibe (ohne DC-Offset) </gallery> Die Leistungsaufnahme lässt sich anhand der Umlaufzeit wie folgt berechnen: <math> P=\frac{1}{t}\frac{\textrm{rot}}{\textrm{s}}\cdot \frac{1}{75}\frac{\textrm{kWh}}{\textrm{rot}}\cdot 3600 \frac{\textrm{W}}{\textrm{h}}\cdot 1000\frac{\textrm{W}}{\textrm{kW}} = \frac{1}{t}\frac{\textrm{1}}{\textrm{s}}\cdot \frac{3600\cdot 1000}{75}\textrm{Ws} = \frac{1}{t}\frac{\textrm{1}}{\textrm{s}}\cdot 48000\textrm{Ws} </math> Setzt man die im Screenshot ermittelten 42.6 Sekunden ein, erhält man eine Leistung von ~1127 Watt. Da die Leistung mit der Zeit exponentiell abnimmt, ist bei hohen Leistungsaufnahmen eine relativ hohe Auflösung der Zeit erforderlich. Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: <gallery> Datei:Nrg zaehler auswert.png|Auswerteschaltung Datei:Nrg zaehler pass.png|Zählersignal vor (blau) und nach (gelb) dem Filter </gallery> Links wird der Fototransistor in Sperrrichtung angeschlossen. Der 1µF-Elko und der nachfolgende 100k-Widerstand stellt einen Hochpass mit nicht näher definierter Grenzfrequenz (WolframAlpha sagt [http://www.wolframalpha.com/input/?i=1%2F%282*Pi*100kOhms*1%C2%B5F%29 1.592Hz]) dar. Die Frequenz ist ist im Hinblick auf [[:wpde:Hochpass:Ordnung]], Bauteiletoleranzen und der Zielfrequenz vermutlich nicht einmal ein Richtwert. Der folgende Hochpass hat eine Grenzfrequenz von ca. 16Hz. Hier gilt das gleiche Vertrauen wie in den Tiefpass. Aber alles kein Problem: Die Werte sind weitestgehend unkritisch. Es sind Umläufe im Millihertz-Bereich (also Umlaufdauern in der Größenordnung Sekunden bis Minuten) zu erwarten. Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. [[Datei:Nrg tarifzaehler.jpg|thumb|Tarifzähler, rechts das Fähnchen zum Anzeigen des Tarifs]] Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. [[Datei:Nrg_relais_freigabe.jpg|thumb|Relais für die Stromfreigabe, mit LED]] Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. '''Update 10.10.2010:''' Weasel (IRC) ist beim Anblick der Kennlinie der Temperatursensoren in der Anleitung des Vitosolic 200 blitzschnell darauf gekommen, dass es sich um PT500-Elemente handeln müssen, die jedoch nur für sehr teuer Geld erhältlich sind. Mein anfänglicher Scherz vonwegen 2 PT1000 parallel ergibt PT500 hat sich als gar nicht so dumm erwiesen: Idealerweise sind die Widerstände der Sensoren bei gleicher Temperatur ebenfalls gleich, Durch Parallelschaltung zweier PT1000 kann man sie problemlos an der PT1000 betreiben! Da ich sonst nichts mit meinen 9 Sensoren anzufangen wusste, fristen jetzt 8 dieser als 4 Fühler im Keller ihr dasein: Zwei erfassen die Ein- und Auslasstemperatur an der "Primärseite" der Wärmepumpe, einer sitzt im Warmwasserspeicher in oberster Schicht und der 4. misst (da mir noch nichts besseres einfiel) die Raumtemperatur im Heizkeller, die mangels Isolierung der Rohre deutlich zu hoch ist. '''Update-Ende''' === Was kommt rein? === Auf der Unterseite [[Energieerfassung/Solarleistung]] habe ich beschrieben, wie man anhand einiger Parameter die Leistung der Solaranlage berechnen kann ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. <gallery> Datei:Nrg shield.jpg|Shield des Großhirns Datei:Nrg grosshirn.jpg|Hirn von oben </gallery> ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. <gallery> Datei:Nrg lcd 1.jpg|Home-Screen mit Datum und Uhrzeit Datei:Nrg lcd 2.jpg|Aktueller Stromverbrauch Datei:Nrg lcd 3.jpg|Solardaten: Kollektortemperatur, Pumpenlast und Speichertemp. Datei:Nrg lcd 4.jpg|Debuginfos, Timeouts des TCP/IP-Stacks und Refresh des NTP-Clients </gallery> ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== [[Datei:Nrg json.png|thumb|Exemplarischer JSON-Datensatz]] Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= Aktuelle Firmware, EAGLE-Dateien des Shields (ohne V-Bus-Pegelwandler): [[Datei:Energieerfassung Firmware.zip]] =Nerviges/Todo= *Die interne Uhr hat eine sehr hohe Gangabweichung. Macht sich trotz kurzer NTP-Refresh-Intervallen bemerkbar *Der Speicher für die historischen Daten ist sehr klein. Bei Ausfall der Internetverbindung/Server/Cronjob gibt es zu schnell Lücken *Erfassung des Wasserzählers *Erfassung Außentemperatur =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Pads der LEDs zu groß und Widerstände gegen GND geschaltet) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann *[http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller *Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] af167187c67ba7cf1b022f14e7e83cdffa1731c4 Touchlight 0 92 712 679 2012-03-11T18:58:10Z Chris 2 /* Die Software */ Syntaxhighlighting hinzugefügt wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny13 | Takt = 9,6 | FuseH = FF | FuseL = 7A }} Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. = Leuchtmittel = Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "ultrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos selektieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen, der über zwei Hardware-PWMs verfügt. Um diese auch nutzen zu können, wird die LED-Leiste in zwei Stränge unterteilt. Die Anzahl der LEDs wird einzig durch das Netzteil beschränkt (ein austemustertes SonyEricsson-Ladegerät). Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. = Bedienung = Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. = Theorie = [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> :<math>U\left(t\right) = U_{0} \cdot \left(1-e^{\frac{-t}{R \cdot C}}\right)</math> Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. = Praxis = Um es noch ein wenig anschaulicher zu machen, habe ich das Oszilloskop auf die Schaltung angesetzt. Dazu wurde die Schaltung auf dem Breadboard aufgebaut. Die Ladewiderstände entsprechen wie im Schaltplan 1,1MOhm. Die Sensorfläche mit 28x28mm (7,8 cm²) und 1,5mm Dicke (Dielektrikum: Hartpapier) ist mit 5cm Leitung direkt (ohne Angstwiderstand) mit dem AVR verbunden. Aufgrund der nicht zu verachtenden Kapazität des Breadboards un des Tastkopfes (Impedanz weiß ich gerade nicht auswendig) dürften die Messwerte deutlich verzerrt sein! Die Bilder und Erklärungen dienen daher höchstens zum Veranschaulichen des vorherigen Abschnitts! <gallery> Bild:Touchlight untouched.png|Unberührte Sensorfläche Bild:Touchlight touched.png|Berührte Sensorfläche Bild:Touchlight burst untuched.png|"Abfrageburst" unberührt Bild:Touchlight burst touched.png|"Abfrageburst" berührt </gallery> Im ersten Bild ist der Spannungsverlauf zu sehen, bei dem die Sensorfläche nicht berührt wurde. Entgegen der Datenblattangabe erkennt der AVR den High-Pegel bei 2,58V, wobei es 26,6µs dauert, bis dieser Wert erreicht wird. Wird die komplette Sensorfläche mit der Hand abgedeckt, steigt die Dauer bis zum Schwellenwert auf 41µs, also etwa das 1,5-fache der Zeit der unberührten Sensorfläche. Bei einem CPU-Takt von 9,6MHz sind dies 394 Taktzyklen (im Vergleich zu 256 Taktzyklen vorher), die man recht entspannt messen kann. In den letzten beiden Bildern ist ein kompletter "Abfrageburst" (5 Einzelabfragen) zu sehen. Auch wenn es auf den ersten Blick irreführend ist, die Bildunterschriften sind korrekt. Bei den beiden Fotos habe ich (dummerweise) eine andere Zeitbasis gewählt. Auch bei den Bursts hat das Zeitverhältnis zwischen unberührt und berührt den Faktor 1,5. Wobei ich dazu sagen muss: '''Traue keiner Statistik, die du nicht selbst gefälscht hast!''' Die gemessenen Dauern schwanken insbesondere beim Berühren der Sensorfläche immens. Hauptursache dürfte wahrscheinlich der Elektrosmog sein, der die 50 bzw. 100Hz (Halbwellen) aus dem Stromnetz beisteuert... = Die Software = Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <geshi lang=c> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~pin; //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & pin) && --sampletime); //Zeit messen KEYDDR |= pin; //Pin als Ausgang -> entladen return sampletime; } </geshi> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <geshi lang=c> ... i = 0; n = 6; while(--n) { i += getcap(1<<PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </geshi> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <geshi lang=c> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </geshi> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. == Download == [[Datei:Touch_1.0.zip]] Enthält sowohl den simplen Touchsensor als auch die Version mit serieller Ausgabe. CPU-Takt muss jeweils 9,6MHz sein (Bei Fabrikneuen Tiny13ern muss die CKDIV8-Fuse entfernt werden, damit das Teil bei vollem Takt läuft), der Rest nach eigenem Ermessen. Stromlaufpläne ist bei beiden Sourcen gleich, bei TouchSense ist zusätzlich der (nicht-invertierte) UART auf PBO. Dort werden die Messwerte der beiden Sensoren Tab-getrennt ausgegeben. die Konstante MINDELAY für den UART-Pause in suart.c muss wahrscheinlich angepasst werden. [[Category:AVR]] 50a5d462ca3dc5b076b211b10b23c5e293e4bba7 Datei:EMR7370 aussen.jpg 6 282 713 2012-03-11T19:48:42Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:EMR7370 RXM01.jpg 6 283 714 2012-03-11T21:09:51Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:EMR7370 bottom.jpg 6 284 715 2012-03-11T21:09:55Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:EMR7370 LA1.png 6 285 716 2012-03-11T21:20:48Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:EMR7370 LA2.png 6 286 717 2012-03-11T21:33:43Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e EMR7370 0 287 718 2012-03-11T21:51:16Z Chris 2 Seite erstellt, Rest kommt noch. wikitext text/x-wiki [[Datei:EMR7370_aussen.jpg|thumb|Empfänger]] Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade. Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch. =Schaltungsanalyse= Der erste Schritt zur Analyse des Ganzen führt natürlich über den Schraubendreher. Im Inneren befindet sich eine große Leiterplatte, auf der eine kleinere Huckepack sitzt. Da an dieser eine Antenne angelötet ist, ist der Funkempfänger schnell gefunden. Der Silkscreen verrät sogar die Anschlussbelegung desselben. Nachdem bei der ersten Untersuchung die Hälfte der Beschriftung durch das Modul verdeckt war, habe ich diese nochmal weiter oben angebracht, deswegen bitte nicht wundern. Auch die Buchsen- & Stiftleiste sind nicht original, sondern von mir hinzugefügt. Da die andere Seite der Leiterplatte nicht spektakulärer ist, habe ich auf ein Foto verzichtet. Das einzig halbwegs interessante ist ein I²C-EEPROM, dessen Takt- und Datenleitung an der Stiftleiste liegt. <gallery> Datei:EMR7370_bottom.jpg|Platinenunterseite Datei:EMR7370_RXM01.jpg|Funkmodul RXM01 </gallery> Zu dem Funkmodul konnte ich im Internet nur die Bestätigung über die Existenz finden, wobei dort selbst die Angabe der Betriebsspannung unterschiedlich war. =Protokollanalyse= Da die Leiterplatte mit den Bezeichnungen SCK/SDI/SDO/NSEL schon auf SPI hindeutet wusste ich ungefähr, worauf ich mich einlasse. Mit der Stift- und Buchsenleiste zwischen Funkmodul und Hauptplatine sollte es relativ einfach sein, auf dem untersten Layer (Bitübertragungsschicht, wenn man es an dieser Stelle so nennen will) zu analysieren. Also Probes angeschlossen und gleich mal den neuen Logic Analyzer getestet. Die erste Messung zeigt die übertragenen Daten vom Einschalten des Empfängers bis zur ersten Anzeige der Messwerte. Genauer betrachtet und mit aktiviertem SPI-Analyzer sieht man auch, was übertragen wird: <gallery> EMR7370_LA1.png|Übersicht EMR7370_LA2.png|Zoom auf den ersten Block </gallery> Zur mutmaßlichen Initialisierung werden folgende Daten übertragen: <pre> 0x90D9 0xA67C 0xC080 0xC081 (500ms Pause) 0xCE85 0xCE87 0xC4AB 0xC823 0xC6C7 0xB014 0xC205 0xC080 (188ms Pause) 0xC081 (4ms Pause) 0x94D9 0xC209 (5ms Pause) 0x00 0x90D9 0xC080 (52ms Pause) 0xC081 </pre> Auch nach dem Empfang eines Datenpaketes sendet die Elektronik noch ein paar Päckchen an den Empfänger: </pre> 0xCE85 0xC080 (längere Pause) 0xC081 (3ms Pause) 0xCE85 0xCE87 </pre> Hier fällt auf, dass 0xC080 und 0xC081 oft in Kombination (siehe auch oben) und vor allem in der Nähe eines Datenempfangs auftreten. Ob dahinter eine Kausalität steckt?!? Da ich mich schon einmal kurzzeitig mit Funkmodule aus dem Hause HopeRF auseinandergesetzt habe und deren Produkte eine ähnliche Bezeichnung haben (z. B. RFM01), habe ich auf gut Glück auf deren Homepage nochmal vorbei geschaut. Wie durch meine vorherige Recherche erwartet, fand ich nichts, was genauso hieß oder aussah wie mein Funkmodul, allerdings blieb ich kurz am Datenblatt des RFM01 hängen. Nachdem ich ein paar der Befehle in Hex umrechnete, stellte sich ein deutlicher Wiedererkennungswert heraus! Alle (bis auf einen) der gesendeten Datensätze ließ sich sinnvoll durch die Inhalte des Datenblatts rekonstruieren - also ein voller Erfolg. Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht. =Datenanalyse= Für die Datenanalyse erzeugte ich mir durch eine definierte Last (vulgo: Glühlampe) Werte, die ich in Excel zwischen den gesendeten und auf dem EMR angezeigten Werten abglich. Dabei stellte sich sehr schnell heraus, dass die Daten mehr oder weniger im Klartext gesendet werden. Hier eine kleine Tabelle einiger Werte: (to be continued...) cddafefdb34e007fadb92f215457f0b680fca9ac 719 718 2012-03-11T22:01:30Z Chris 2 wikitext text/x-wiki [[Datei:EMR7370_aussen.jpg|thumb|Empfänger]] Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade. Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch. =Schaltungsanalyse= Der erste Schritt zur Analyse des Ganzen führt natürlich über den Schraubendreher. Im Inneren befindet sich eine große Leiterplatte, auf der eine kleinere Huckepack sitzt. Da an dieser eine Antenne angelötet ist, ist der Funkempfänger schnell gefunden. Der Silkscreen verrät sogar die Anschlussbelegung desselben. Nachdem bei der ersten Untersuchung die Hälfte der Beschriftung durch das Modul verdeckt war, habe ich diese nochmal weiter oben angebracht, deswegen bitte nicht wundern. Auch die Buchsen- & Stiftleiste sind nicht original, sondern von mir hinzugefügt. Da die andere Seite der Leiterplatte nicht spektakulärer ist, habe ich auf ein Foto verzichtet. Das einzig halbwegs interessante ist ein I²C-EEPROM, dessen Takt- und Datenleitung an der Stiftleiste liegt. <gallery> Datei:EMR7370_bottom.jpg|Platinenunterseite Datei:EMR7370_RXM01.jpg|Funkmodul RXM01 </gallery> Zu dem Funkmodul konnte ich im Internet nur die Bestätigung über die Existenz finden, wobei dort selbst die Angabe der Betriebsspannung unterschiedlich war. =Protokollanalyse= Da die Leiterplatte mit den Bezeichnungen SCK/SDI/SDO/NSEL schon auf SPI hindeutet wusste ich ungefähr, worauf ich mich einlasse. Mit der Stift- und Buchsenleiste zwischen Funkmodul und Hauptplatine sollte es relativ einfach sein, auf dem untersten Layer (Bitübertragungsschicht, wenn man es an dieser Stelle so nennen will) zu analysieren. Also Probes angeschlossen und gleich mal den neuen Logic Analyzer getestet. Die erste Messung zeigt die übertragenen Daten vom Einschalten des Empfängers bis zur ersten Anzeige der Messwerte. Genauer betrachtet und mit aktiviertem SPI-Analyzer sieht man auch, was übertragen wird: <gallery> EMR7370_LA1.png|Übersicht EMR7370_LA2.png|Zoom auf den ersten Block </gallery> Zur mutmaßlichen Initialisierung werden folgende Daten übertragen: <pre> 0x90D9 0xA67C 0xC080 0xC081 (500ms Pause) 0xCE85 0xCE87 0xC4AB 0xC823 0xC6C7 0xB014 0xC205 0xC080 (188ms Pause) 0xC081 (4ms Pause) 0x94D9 0xC209 (5ms Pause) 0x00 0x90D9 0xC080 (52ms Pause) 0xC081 </pre> Auch nach dem Empfang eines Datenpaketes sendet die Elektronik noch ein paar Päckchen an den Empfänger: </pre> 0xCE85 0xC080 (längere Pause) 0xC081 (3ms Pause) 0xCE85 0xCE87 </pre> Hier fällt auf, dass 0xC080 und 0xC081 oft in Kombination (siehe auch oben) und vor allem in der Nähe eines Datenempfangs auftreten. Ob dahinter eine Kausalität steckt?!? Da ich mich schon einmal kurzzeitig mit Funkmodule aus dem Hause HopeRF auseinandergesetzt habe und deren Produkte eine ähnliche Bezeichnung haben (z. B. RFM01), habe ich auf gut Glück auf deren Homepage nochmal vorbei geschaut. Wie durch meine vorherige Recherche erwartet, fand ich nichts, was genauso hieß oder aussah wie mein Funkmodul, allerdings blieb ich kurz am Datenblatt des RFM01 hängen. Nachdem ich ein paar der Befehle in Hex umrechnete, stellte sich ein deutlicher Wiedererkennungswert heraus! Alle (bis auf einen) der gesendeten Datensätze ließ sich sinnvoll durch die Inhalte des Datenblatts rekonstruieren - also ein voller Erfolg. Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht. =Datenanalyse= Für die Datenanalyse erzeugte ich mir durch eine definierte Last (vulgo: Glühlampe) Werte, die ich in Excel zwischen den gesendeten und auf dem EMR angezeigten Werten abglich. Dabei stellte sich sehr schnell heraus, dass die Daten mehr oder weniger im Klartext gesendet werden. Hier eine kleine Tabelle einiger Werte: {| class="wikitable sortable" |- ! U !! I !! P !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 !! 9 !! 10 !! 11 |- | 221,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 06 || BB || 40 || 00 || F4 |- | 221,5 || 0,17 || 39 || 25 || 6A || 54 || 72 || 40 || 4E || 00 || B1 || BB || 40 || 00 || 71 |- | 222,5 || 0,17 || 39,5 || 25 || 6A || 54 || 72 || 40 || 4F || 00 || B2 || BD || 40 || 01 || 6C |- | 222,5 || 0,06 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 43 || BD || 40 || 01 || 25 |- | 223 || 0,03 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 25 || BE || 40 || 01 || 42 |- | 222 || 0,03 || 2 || 25 || 6a || 54 || 72 || 40 || 04 || 00 || 20 || BC || 40 || 01 || 4A |- | 222,5 || 0,06 || 1 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3E || BD || 40 || 01 || 2D |- | 223,5 || 0,06 || 1 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3C || BF || 40 || 01 || 2D |- | 222,5 || 0,31 || 29 || 25 || 6A || 54 || 72 || 40 || 3A || 01 || 3E || BD || 40 || 01 || F4 |- | 222 || 0,37 || 42 || 25 || 6A || 54 || 72 || 40 || 54 || 01 || 74 || BC || 40 || 01 || A5 |- | 223 || 0,35 || 42,5 || 25 || 6A || 54 || 72 || 40 || 55 || 01 || 66 || BE || 40 || 02 || AF |- | 221,5 || 0,19 || 38 || 25 || 6A || 54 || 72 || 40 || 4C || 00 || BF || BB || 40 || 02 || 63 |- | 224 || 0,13 || 12,5 || 25 || 6A || 54 || 72 || 40 || 19 || 00 || 8B || C0 || 40 || 03 || C4 |- | 220,5 || 0,02 || 1 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 1A || B9 || 40 || 04 || 52 |} Die ersten drei Spalten geben die Spannung in Volt, den Strom in Ampere sowie die Leistung in Watt an, alle weiteren die empfangenen Bytes im Hex-Format. (to be continued...) f3bbcbcf61de8ffcf5a6cd4d73feb30420b2242c Datei:SNES 2a.jpg 6 288 720 2012-03-14T21:07:03Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:SNES 2b.jpg 6 289 721 2012-03-14T21:07:07Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e SNES-Joypad 0 35 722 469 2012-03-14T21:09:05Z Chris 2 Bilder eines anderen Aufbaus ausgegraben wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = DD | FuseL = E1 | FuseE = FF }} Als Kind hatte ich mir mal (ja, aus eigener Tasche) einen Super Nintendo gekauft. Nachdem er die Jahre leider nicht überlebt hat und ich doch ab und an mal ein bisschen Verlangen nach SNES habe, griff ich auf Emulatoren für den PC zurück. So gut die Programme auch sind - man hat ein Problem: man muss auf der Tastatur spielen. Das mag bei manchen Spielen noch gehen, wenn man jedoch in brenzliche Situationen kommt, braucht man dann doch die etwas trainierteren Daumen. Irgendwann kam ich auf die Idee, einfach das Gamepad an den PC anzuschließen. Mit einem Nachbau eines SNES-Gamepads, das ich mal geschenkt bekommen habe, funktionierte das ziemlich gut. Im Pad selbst waren zwei CD4021 (Schieberegister) verbaut. Die Funktionsweise des Gamepads ist somit genauso simpel wie... simpel. Wenn die CPU in der Konsole den Controller auslesen will, werden die Daten per Latch in das Register geladen, von wo es dann seriell ausgelesen werden kann. [[Bild:SNES-stecker.jpg|thumb|Anschlussbelegung am Stecker]] Die Beschaltung im Controller ist folgendermaßen: {| ! Pin|| Farbe || Funktion |- | 1 || braun || GND |- | 2 || rot || Data |- | 3 || orange || Latch |- | 4 || gelb || Clock |- | 5 || weiß || Vcc |} Bei meiner ersten Entwicklung war das Gamepad am Parallel-Port angeschlossen und wurde von einem kleinen VB-Programm ausgelesen. Die Tastenanschläge wurden dann per DLL als Tastatur-Eingaben simuliert. Das ganze hatte nur ein paar Nachteile: * Die Software war nicht besonders schön * Der Parallelport wurde (mal wieder) zweckentfremdet * Man muss hinter den PC kriechen, wenn man wieder etwas drucken will * Das Ganze ist einfach nicht rund (vorangegangene Punkte) * Mein Notebook hat weder eine parallele noch serielle Schnittstelle Irgendwann entdeckte ich [http://www.obdev.at/products/vusb/index-de.html V-USB], eine Software-Implementierung von USB in AVRs. Als Projekt war [http://www.raphnet.net/electronique/snes_nes_usb/index_en.php SNES/NES gamepad (and mouse) to USB adapter] verlinkt. Die Schaltung habe ich mir dann relativ zügig aufgebaut, um zu testen, ob da wirklich das dahintersteckt, was ich mir erwartet hatte. Tatsächlich meldete Windows 2s nach dem Einstecken der Konstruktion eine neue Hardware. Nur die Tatsache, dass an einem 28-Pin-Mikrocontroller nur ca. 10 Pins und auf den 8KB Speicher nur 3 belegt waren und das Ganze nicht richtig im Gamecontroller untergebracht werden konnte, störte mich ein wenig. Vor kurzem las ich dann folgendes auf obdev.at: <pre> New: Internal RC Oscillator Supported AVR-USB supports the internal RC oscillator of all AVRs with internal high frequency PLL, such as the ATTiny45 or ATTiny26. No external crystal is needed on these devices! See the EasyLogger example for details. </pre> Das war das, worauf ich gewartet hatte: Der ATTiny45 hat 8 Beine, wofür 2 für USB und weitere 3 für die Standardbeschaltung verwendet werden. Somit bleiben genau die benötigten drei Anschlüsse für das Gamepad frei. Die Beispielanwendung für die Implementierung ([http://www.obdev.at/products/avrusb/easylogger.html EasyLogger]) zielt schon sehr gut in die Richtung, in die ich gehen will. Der Großteil des Quelltextes konnte beibehalten werden, Teile kamen von Raph und wurden ziemlich stark umgebaut. Nachdem ich einige Wochen zuvor kläglich daran gescheitert bin, die Software von oben auf den ATTiny2313 zu portieren, nahm ich mir zum Ziel, den Quelltext so klein wie möglich zu gestalten. Nach etlichen Optimierversuchen und Brennvorgängen war es dann geschafft: Das kompilierte Programm ist exakt 2000 Byte groß. Leider hat der Device-Name etwas darunter gelitten - es ist allerdings noch deutlich erkennbar, worum es sich handelt. Ein weiteres Ziel war, die Elektronik im Controller unterzubringen, sodass nur noch ein USB-Kabel ohne weitere Elektronik am PC angeschlossen wird. Netterweise ist im Gamepad ziemlich viel Platz vorhanden, welcher erlaubt, selbst einen DIP-IC aufgelötet auf einer Platine zu fassen. Also flugs die Schaltung vom Steckbrett auf die Platine bringen. Nach dem ersten Test am PC war ich etwas irritiert: kein fröhliches "Plüm-Plim" vom PC, stattdessen kam nach einigen Wartesekunden ein "Plopp" aus den Lautsprechern: "Hardware wurde nicht erkannt". IC ausgelötet und wieder aufs Steckbrett: "Plüm-Plim" (Hardware erkannt). Auch nach langem Suchen war kein Fehler in der Schaltung zu finden. Also zurück an den Anfang: [[PLL im ATTiny45 kalibrieren]]. [[Bild:SNES-einbau.jpg|thumb|Einbau des V-USB-Controllers im SNES-Gamepad]] Nach ein paar Versuchen klappte es auch und ich konnte das Gamepad wieder schließen. Wenn mich jetzt die Lust packt heißt es nur noch Controller vorne am PC an einem freien USB-Port anschließen und losspielen. Da der Aufbau auf Lochraster zwar "ganz nett" ist, aber noch nicht der Weisheit letzter Schluss ist, habe eine kleine Schaltung + Platine in SMD in EAGLE erstellt: <gallery> Bild:Snes-usb_sch.png|Stromlaufplan Bild:SNES-brd.png|SMD-Layout der Schaltung Bild:Snes-usb-2313_sch.png|Stromlaufplan der ATtiny2313-Version </gallery> Die Schaltung ist zwar nicht gerade ideal zum Brennen des AVRs, aber evtl. könnte es klappen, wenn man die Anschlüsse für USB (oben) und für den SNES-Controllers (unten) ausnutzt. Leider kommt man nicht 'drum, einen Draht direkt an RESET zu löten. Platz für einen Testpin ist leider nicht mehr vorhanden. Die Anschlussbelegungen sind jeweils nach den "Standards". Auf der SNES-Seite wie oben angegeben, auf USB-Seite so wie im USB-Standard angegeben (Näheres ist dem Stromlaufplan in der ZIP-Datei zu entnehmen). Eine weitere, nicht unbedingt schönere Methode ist, die Schaltung fliegend aufzubauen. Für einen zweiten Controller habe ich diese Methode gewählt: <gallery> Datei:SNES_2a.jpg|Ja, der Controller sah wirklich so aus Datei:SNES_2b.jpg|von unten </gallery> = Downloads = Die Firmware ist unkompiliert, da der OSCCAL-Wert nicht automatisch ermittelt wird. Weiterhin wurde kein Kompilat beigelegt, da das verwendete VID/PID-Paar (siehe usbconfig.h) nicht mir gehört und von jedem, der die Hardware einsetzt durch sein Paar ersetzt werden muss. (Wenn man die Schaltung für sich daheim privat betreibt, sollte es jedoch keine Probleme geben) *[[Datei:SNES-USB.zip]] Firmware OHNE automatische Kalibrierung *[[Datei:SNES-USB-autocal.zip]] Firmware MIT automatischer Kalibrierung und Hex-Datei *[[Datei:Snes-usb-2313.zip]] Firmware für ATtiny2313 == Nachtrag (07/2009) == Das Kalibrieren des PLLs kann seit einiger Zeit wegfallen - es gibt nun die Möglichkeit, die PLL anhand der USB-Framelänge beim Anschließen der USB-Devices zu kalibrieren. Habe es selber schon erfolgreich getestet. Näheres dazu: [http://vusb.wikidot.com/examples#toc4 Clocking the AVR from the RC oscillator with auto-calibration]. Achtung: DIE FIRMWARE IN SNES-USB.zip HIER ENTHÄLT DIESES FEATURE NOCH NICHT! ===Nachtrag (03/2010)=== Ich habe jetzt zusätzlich die Firmware für den ATtiny2313 und die für den ATtiny45 mit automatischer Kalibrierung der PLL hochgeladen. Am Notebook meiner Schwester gab es mit angeschlossenem Gamepad mit Autocal-Firmware ein paar Bluescreens. Ob diese tatsächlich von der Firmware ausgelöst wurde, kann ich nicht mit absoluter Sicherheit sagen. Ich weise einfach mal auf den [[Hobbyelektronik.org:Über_Hobbyelektronik.org#Haftungsausschluss|Haftungsausschluss]] hin. [[Category:PC]] [[Category:AVR]] [[Category:USB]] f5e11fd074e0b85a0f3786eba9f785e27e1ce2a0 723 722 2012-03-14T21:09:52Z Chris 2 Controller != Controller wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny45 | Takt = 16,5 | FuseH = DD | FuseL = E1 | FuseE = FF }} Als Kind hatte ich mir mal (ja, aus eigener Tasche) einen Super Nintendo gekauft. Nachdem er die Jahre leider nicht überlebt hat und ich doch ab und an mal ein bisschen Verlangen nach SNES habe, griff ich auf Emulatoren für den PC zurück. So gut die Programme auch sind - man hat ein Problem: man muss auf der Tastatur spielen. Das mag bei manchen Spielen noch gehen, wenn man jedoch in brenzliche Situationen kommt, braucht man dann doch die etwas trainierteren Daumen. Irgendwann kam ich auf die Idee, einfach das Gamepad an den PC anzuschließen. Mit einem Nachbau eines SNES-Gamepads, das ich mal geschenkt bekommen habe, funktionierte das ziemlich gut. Im Pad selbst waren zwei CD4021 (Schieberegister) verbaut. Die Funktionsweise des Gamepads ist somit genauso simpel wie... simpel. Wenn die CPU in der Konsole den Controller auslesen will, werden die Daten per Latch in das Register geladen, von wo es dann seriell ausgelesen werden kann. [[Bild:SNES-stecker.jpg|thumb|Anschlussbelegung am Stecker]] Die Beschaltung im Controller ist folgendermaßen: {| ! Pin|| Farbe || Funktion |- | 1 || braun || GND |- | 2 || rot || Data |- | 3 || orange || Latch |- | 4 || gelb || Clock |- | 5 || weiß || Vcc |} Bei meiner ersten Entwicklung war das Gamepad am Parallel-Port angeschlossen und wurde von einem kleinen VB-Programm ausgelesen. Die Tastenanschläge wurden dann per DLL als Tastatur-Eingaben simuliert. Das ganze hatte nur ein paar Nachteile: * Die Software war nicht besonders schön * Der Parallelport wurde (mal wieder) zweckentfremdet * Man muss hinter den PC kriechen, wenn man wieder etwas drucken will * Das Ganze ist einfach nicht rund (vorangegangene Punkte) * Mein Notebook hat weder eine parallele noch serielle Schnittstelle Irgendwann entdeckte ich [http://www.obdev.at/products/vusb/index-de.html V-USB], eine Software-Implementierung von USB in AVRs. Als Projekt war [http://www.raphnet.net/electronique/snes_nes_usb/index_en.php SNES/NES gamepad (and mouse) to USB adapter] verlinkt. Die Schaltung habe ich mir dann relativ zügig aufgebaut, um zu testen, ob da wirklich das dahintersteckt, was ich mir erwartet hatte. Tatsächlich meldete Windows 2s nach dem Einstecken der Konstruktion eine neue Hardware. Nur die Tatsache, dass an einem 28-Pin-Mikrocontroller nur ca. 10 Pins und auf den 8KB Speicher nur 3 belegt waren und das Ganze nicht richtig im Gamecontroller untergebracht werden konnte, störte mich ein wenig. Vor kurzem las ich dann folgendes auf obdev.at: <pre> New: Internal RC Oscillator Supported AVR-USB supports the internal RC oscillator of all AVRs with internal high frequency PLL, such as the ATTiny45 or ATTiny26. No external crystal is needed on these devices! See the EasyLogger example for details. </pre> Das war das, worauf ich gewartet hatte: Der ATTiny45 hat 8 Beine, wofür 2 für USB und weitere 3 für die Standardbeschaltung verwendet werden. Somit bleiben genau die benötigten drei Anschlüsse für das Gamepad frei. Die Beispielanwendung für die Implementierung ([http://www.obdev.at/products/avrusb/easylogger.html EasyLogger]) zielt schon sehr gut in die Richtung, in die ich gehen will. Der Großteil des Quelltextes konnte beibehalten werden, Teile kamen von Raph und wurden ziemlich stark umgebaut. Nachdem ich einige Wochen zuvor kläglich daran gescheitert bin, die Software von oben auf den ATTiny2313 zu portieren, nahm ich mir zum Ziel, den Quelltext so klein wie möglich zu gestalten. Nach etlichen Optimierversuchen und Brennvorgängen war es dann geschafft: Das kompilierte Programm ist exakt 2000 Byte groß. Leider hat der Device-Name etwas darunter gelitten - es ist allerdings noch deutlich erkennbar, worum es sich handelt. Ein weiteres Ziel war, die Elektronik im Controller unterzubringen, sodass nur noch ein USB-Kabel ohne weitere Elektronik am PC angeschlossen wird. Netterweise ist im Gamepad ziemlich viel Platz vorhanden, welcher erlaubt, selbst einen DIP-IC aufgelötet auf einer Platine zu fassen. Also flugs die Schaltung vom Steckbrett auf die Platine bringen. Nach dem ersten Test am PC war ich etwas irritiert: kein fröhliches "Plüm-Plim" vom PC, stattdessen kam nach einigen Wartesekunden ein "Plopp" aus den Lautsprechern: "Hardware wurde nicht erkannt". IC ausgelötet und wieder aufs Steckbrett: "Plüm-Plim" (Hardware erkannt). Auch nach langem Suchen war kein Fehler in der Schaltung zu finden. Also zurück an den Anfang: [[PLL im ATTiny45 kalibrieren]]. [[Bild:SNES-einbau.jpg|thumb|Einbau des V-USB-Controllers im SNES-Gamepad]] Nach ein paar Versuchen klappte es auch und ich konnte das Gamepad wieder schließen. Wenn mich jetzt die Lust packt heißt es nur noch Controller vorne am PC an einem freien USB-Port anschließen und losspielen. Da der Aufbau auf Lochraster zwar "ganz nett" ist, aber noch nicht der Weisheit letzter Schluss ist, habe eine kleine Schaltung + Platine in SMD in EAGLE erstellt: <gallery> Bild:Snes-usb_sch.png|Stromlaufplan Bild:SNES-brd.png|SMD-Layout der Schaltung Bild:Snes-usb-2313_sch.png|Stromlaufplan der ATtiny2313-Version </gallery> Die Schaltung ist zwar nicht gerade ideal zum Brennen des AVRs, aber evtl. könnte es klappen, wenn man die Anschlüsse für USB (oben) und für den SNES-Controllers (unten) ausnutzt. Leider kommt man nicht 'drum, einen Draht direkt an RESET zu löten. Platz für einen Testpin ist leider nicht mehr vorhanden. Die Anschlussbelegungen sind jeweils nach den "Standards". Auf der SNES-Seite wie oben angegeben, auf USB-Seite so wie im USB-Standard angegeben (Näheres ist dem Stromlaufplan in der ZIP-Datei zu entnehmen). Eine weitere, nicht unbedingt schönere Methode ist, die Schaltung fliegend aufzubauen. Für einen zweiten Controller habe ich diese Methode gewählt: <gallery> Datei:SNES_2a.jpg|Ja, die Leiterplatte sah wirklich so aus Datei:SNES_2b.jpg|von unten </gallery> = Downloads = Die Firmware ist unkompiliert, da der OSCCAL-Wert nicht automatisch ermittelt wird. Weiterhin wurde kein Kompilat beigelegt, da das verwendete VID/PID-Paar (siehe usbconfig.h) nicht mir gehört und von jedem, der die Hardware einsetzt durch sein Paar ersetzt werden muss. (Wenn man die Schaltung für sich daheim privat betreibt, sollte es jedoch keine Probleme geben) *[[Datei:SNES-USB.zip]] Firmware OHNE automatische Kalibrierung *[[Datei:SNES-USB-autocal.zip]] Firmware MIT automatischer Kalibrierung und Hex-Datei *[[Datei:Snes-usb-2313.zip]] Firmware für ATtiny2313 == Nachtrag (07/2009) == Das Kalibrieren des PLLs kann seit einiger Zeit wegfallen - es gibt nun die Möglichkeit, die PLL anhand der USB-Framelänge beim Anschließen der USB-Devices zu kalibrieren. Habe es selber schon erfolgreich getestet. Näheres dazu: [http://vusb.wikidot.com/examples#toc4 Clocking the AVR from the RC oscillator with auto-calibration]. Achtung: DIE FIRMWARE IN SNES-USB.zip HIER ENTHÄLT DIESES FEATURE NOCH NICHT! ===Nachtrag (03/2010)=== Ich habe jetzt zusätzlich die Firmware für den ATtiny2313 und die für den ATtiny45 mit automatischer Kalibrierung der PLL hochgeladen. Am Notebook meiner Schwester gab es mit angeschlossenem Gamepad mit Autocal-Firmware ein paar Bluescreens. Ob diese tatsächlich von der Firmware ausgelöst wurde, kann ich nicht mit absoluter Sicherheit sagen. Ich weise einfach mal auf den [[Hobbyelektronik.org:Über_Hobbyelektronik.org#Haftungsausschluss|Haftungsausschluss]] hin. [[Category:PC]] [[Category:AVR]] [[Category:USB]] 8d4c19a768a2ba50dee9e3f54c213b21d87e64b7 Datei:Kameratimer 1.jpg 6 290 724 2012-03-14T21:10:31Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Kameratimer 2.jpg 6 291 725 2012-03-14T21:10:44Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Kameratimer 3.jpg 6 292 726 2012-03-14T21:10:51Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Kameratimer 4.jpg 6 293 727 2012-03-14T21:11:05Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Kameratimer 0 192 728 546 2012-03-14T21:12:08Z Chris 2 doch noch ein paar Bilder zum Aufbau gefunden wikitext text/x-wiki [[Datei:Kameratimer.JPG|thumb|Der fertige Timer samt Kamera]] [[Datei:Kameratimer gehaeusse.jpg|thumb|Gehäuse des Timers - das mit den Ausschnitten übe ich noch...]] Nachdem sich meine alte Kompaktkamera kurzzeitig [http://hobbyelektronik.org/b/?p=132 verabschiedet] hat und ich für den Urlaub etwas kleineres wollte, legte ich mir einen Ersatz zu. Ergebnis: Es liegen 3 funktionierende Digitalkameras herum. Um die wieder gut funktionierende PowerShot nicht in der Ecke vergammeln zu lassen und mich schon länger Zeitraffer-Aufnahmen interessieren, beschloss ich, das Teil ein wenig umzubauen: = Fernauslöser für die PowerShot A95 = Das Fernauslösen der A95 ist zwar möglich, jedoch nur per PC und einer Software von Canon. Mit ihr können zwar auch Zeitraffer-Aufnahmen gemacht werden, allerdings ist es nicht besonders effizient und auch umständlich, den Computer zu transportieren bzw. tagelang laufen zu lassen. Eine weitere Möglichkeit der Fernauslösung existiert nicht, da weder Auslöser-Eingang noch eine modifizierte Firmware bzw. Erweiterung wie [http://chdk.wikia.com/wiki/CHDK CHDK] für die Kamera existiert. Also muss man selber für den Fernauslöser-Eingang sorgen. Die Peripherie rund um die Hauptplatine ist hauptsächlich in Flexprint (dieses Polyimid-Zeug) ausgeführt, das man nicht gerade mit einem Dachrinnenbrater bearbeiten sollte. Gleichzeitg sind die Leiterbahnen sehr fein und lassen sich manuell schlecht verfolgen. Hier hilft es, die verdächtigen Stellen zu fotografieren und die Leiterbahnen mit Bildbearbeitung zu markieren und verfolgen. Praktischerweise enden die für den Auslöser relevanten Leitungen an einer gut erreichbaren Stelle und sind gut lötbar. Mit Fädeldraht kontaktiert muss das Zeug nur noch von außen erreichbar werden. Zum Glück findet sich im Gehäuse noch ein freies Fleckchen: neben dem Stromanschluss ist genug Platz für eine Buchsenleiste im 1,27mm Rastermaß. Für diese muss lediglich die Gummiabdeckung der restlichen Buchsen weichen. Mit Epoxid-Kleber hält das Teil bombenfest und die Kamera sieht von außen fast normal aus. <gallery> Datei:Kameratimer_.jpg|Oberseite der Kamera Datei:Kameratimer_.jpg|Rückseite der Kamera Datei:Kameratimer_.jpg|Drähte für halb und ganz gedrückten Auslöser Datei:Kameratimer_.jpg|Masseanschluss </gallery> = Auslöser = {{Infobox AVR | Typ = ATtiny26 | Takt = 3,2768 | FuseH = F4 | FuseL = B7 }} Jetzt muss die Kamera "nur noch" ausgelöst werden. Schließlich wäre das Ziel verfehlt, wenn man den ganzen Tag mit Uhr neben der Knipse sitzen und aufs Knöpfchen drücken müsste. Diesen Job soll ein ATTiny26 übernehmen, dessen Speicher sich im Nachhinein als etwas knapp erwiesen hat. Um den AVR versammeln sich nur wenige Komponenten: Als Taktquelle dient ein 3,2768MHz Quarz, die Anzeige übernimmt ein 1x20 Character LCD und zur Eingabe dient ein Drehgeber mit Taster den ich mal aus einer HP-Knipse geschlachtet habe. Zum Auslösen selbst wird ein einfacher Optokoppler (Typ weitestgehend unbekannt) verwendet. Der Drehgeber hat einen Vorteil und gleichzeitig auch Nachteil: Eine Raste sind zwei Übergänge der Ausgänge. Dadurch wird die Software nicht kompatibel mit anderen Drehgebern. Vorteil: die Auswertung ist etwas kompakter. Das LCD wird (nach Anfangsschwierigkeiten mit einer anderen Bibliothek) mit dem großartigen Code von [http://www.jump.to/fleury Peter Fleury] angesteuert. == Bedienkonzept == Ohne gute Bedienbarkeit hilft der beste Code im Hintergrund nichts. Zugegebenermaßen muss man sich bei einer etwas besseren Eieruhr keine Gedanken über die Usability machen, ein klein bisschen Komfort sollte aber drin sein. Die Software kennt vier Menüpunkte: * Low-Zeit des Ausgangs (L) * High-Zeit des Ausgangs (H) * Anzahl der Schaltvorgänge (n) * Statusanzeige/Verbleibende Zeit zum Zustandswechsel (R) Die Dauer der High-Zeit ist für Langzeitbelichtungen im BULB-Modus (also deutlich über den maximalen 30 Sekunden – nur für Spiegelreflexen relevant) gedacht. Mit dem Drehgeber kann man im ersten Modus durch die verschiedenen Menüpunkte wechseln. Drückt man den Drehgeber, wechselt der Modus zur Stellenwahl. Hier kann man nun auswählen, welche Stelle des angezeigten Werts bearbeiten will. Nach einem weiteren Druck kann man dann durch Drehen den Wert erhöhen bzw. verringern. Die verschiedenen Modi rotieren momentan durch. Intuitiver wäre es meiner Meinung noch, wenn man zwischen Wahl der Stelle und Erhöhen/Verringern so lange hin und her wechselt, bis man nicht mehr "am Rädchen dreht". Damit man auch weiß was man macht, wir der aktuelle Modus per Symbol auf dem Display angezeigt. Neben dem Modussymbol wird angezeigt, ob der Timer aktuell läuft (Play-/Stopp-Symbol), da die Parameter auch während dem Laufen des Timers verändert werden können. Bei der Anzeige der verbleibenden Zeit zum Zustandswechsel wird zusätzlich die nächste Flanke (steigend oder fallend) angezeigt. == Software == Herzstück ist der Timer des AVRs, der eine Zeitbasis von 0.1 Sekunden schafft. Dies ist gleichzeitig auch die kleinste einstellbare Einheit. Im Timer-Interrupt wird die komplette Verarbeitung der Schaltzeiten und der Ausgabe übernommen. Das Benutzerinterfache ist komplett im (berüchtigten) Main-Loop untergebracht. Sämtliche Benutzereingaben werden gepollt. Um das Entprellen der Taster zu sparen ist der restliche Code bewusst *hust* ineffizient. == Aufbau == Ursprünglich sollte die Schaltung (aufgrund der geringen Komplexität) auf Lochraster aufgebaut werden. Nachdem ich sowieso ein paar Leiterplatten fertigen lassen wollte, kam das Layout eben noch dazu. <gallery> Bild:Kameratimer_sch.png|Stromlaufplan Bild:Kameratimer_brd.png|Board </gallery> Das verwendete Display hat seine Anschlüsse mit 2x7 Pins auf der linken Seite. Dementsprechend wurde die Anschlussbelegung am Mikrocontroller angepasst. Mit Stift- und Buchsenleiste ist der Abstand zwischen Platine und Display genau so, dass man die ICs sockeln kann. Leider passt der hohe Quarz nicht mehr stehend darunter (zumindest der, den ich da hatte). An zwei Stellen war noch etwas knobeln angesagt: Beim Anschluss der Kamera und des Drehgebers. Leider hatte ich mir beim Test auf dem Breadboard nicht aufgeschrieben, wo was war. Etwas hakelig war auch die Kontrastspannung – aus irgendwelchen Gründen habe ich auch nach längerem probieren keine vernünftige Widerstandskombination gefunden. Schlussendlich habe ich am Rand der Platine ein Poti angelötet. == Anschluss an die Kamera == [[Datei:Canon Klinke.png|thumb|Belegung des 2.5mm-Klinkensteckers für Canon-Fernauslöser]] Der Anschluss für die Kamera ist eine 2,5mm-Klinkenbuchse. Diese hat den Vorteil, dass man die kleineren Spiegelreflexen von Canon direkt mit einem einfachen Klinkenverbinder angeschlossen werden können. Am Fernauslösereingang der SLRs (zumindest an der EOS 400D) liegt eine Spannung von 3,3V an, beim Ziehen auf Masse wird je nach Pin entweder fokussiert oder ausgelöst. Zieht man den Pin zum Auslösen auf Masse, ohne zuvor zu fokussieren (oder auf manuellen Fokus eingestellt zu haben), holt dies die Kamera vor dem Auslösen nach, was den Vorgang verzögert. Dieses Verhalten habe ich bei der PowerShot nicht beobachten können. Wird nur die Leitung zum Auslösen auf Masse gezogen, passiert nichts. Werden beide Leitungen gleichzeitig auf Masse gezogen, löst die Kamera ohne Probleme aus. Um einen zusätzlichen Optokoppler zu sparen, habe ich die Fokussier- und Auslöseleitung im Timer verbunden. Das hat zur Folge, dass die Kamera, wenn sie am Timer angeschlossen ist, auch dann auslöst, wenn man den Auslöser nur halb drückt. Die Verschaltung scheint nach einem Blick auf die Innereien des [http://www.eosdoc.com/manuals/?q=RS-60E3 RS-60E3] üblich zu sein und sollte zu keinen Problemen führen. = Trivia = Die Software/Hardware hat mich ziemlich gefuchst. Aufgrund des Platzmangels war kein Debugging über UART möglich, Hardware für „richtiges“ Debugging ist leider auch nicht vorhanden. Ich habe bis heute nicht herausgefunden, woran sich der AVR gestört hat. Manchmal funktionierte das Teil, manchmal auch nach dem 10. Mal einschalten noch nicht. Auch ein nachträglicher Reset brachte nichts – es war wie verhext. Es war kein offensichtlicher Hard- oder Softwarefehler zu finden. Eines ist sicher: Nie wieder Smileys auf einem Layout. Die Probleme waren auch der Grund dafür, warum ich das Projektchen erst fast ein Jahr nach dem eigentlichen Aufbau dokumentiere. = Tipps für Aufnahmen = Beim ersten Test musste eine Amaryllis herhalten. Aus dem Versuch kommen folgende Erkenntnisse: * Energiesparlampen sind trotz Weißabgleich für die Beleuchtung ungeeignet * Bildausschnitt immer großzügig wählen, zuschneiden kann man später immer noch * Manuellen Fokus verwenden ** Geringere Auslöseverzögerung ** Vermeidung wandern der Schärfeebene ** Schärfenebene so einstellen, damit zum Schluss auch das Interessante scharf ist * Bei der Aufnahmedauer, dem Intervall und dem damit verbundenen Speicherplatzbedarf lieber zweimal rechnen * Bildnummerierung vor der Aufnahme zurücksetzen [[Datei:Kameratimer_schnuller.JPG|thumb|"Stromspar"-Stecker]] Leider löschen die ganzen kompakten Canons den AF-Lock, sobald das Display abgeschaltet wird. Mit einem kleinen Trick kann man das Display abschalten, ohne die Aufnahmeparameter zu beeinflussen: Steckt man eine 3,5mm-Klinke in den Videoausgang, wird das interne Display abgeschaltet. Der Bildsensor bleibt bei diesem „Trick“ jedoch aktiv, was eine deutlich höhere Stromaufnahme im Gegensatz zum Standby-Modus bedeutet. Bei einer zweiten Testaufnahme eines Sonnenuntergangs habe ich festgestellt, dass die automatische Belichtungssteuerung erstaunlich „geschmeidig“ arbeitet. Unter den knapp 400 Fotos waren trotz kurzzeitigem Gegenlicht keine Ausreißer. Als Warnung sei noch angebracht, dass Bildsensoren nicht unbedingt dafür ausgelegt sind, längerer Zeit direkte Sonneneinstrahlung auszuhalten. Auf gut Deutsch: Wenn man einen Zeitraffer von der Sonne macht, kann mit dem Bildsensor dasselbe wie Ameisen passieren, die mit der Lupe brutzelt. = Download = [[Datei:Kameratimer.zip]] c7893eb290c789f5d1fd9dcecc263871a61ef596 729 728 2012-03-14T21:12:37Z Chris 2 und gleich noch die Dateinamen falsch geschrieben wikitext text/x-wiki [[Datei:Kameratimer.JPG|thumb|Der fertige Timer samt Kamera]] [[Datei:Kameratimer gehaeusse.jpg|thumb|Gehäuse des Timers - das mit den Ausschnitten übe ich noch...]] Nachdem sich meine alte Kompaktkamera kurzzeitig [http://hobbyelektronik.org/b/?p=132 verabschiedet] hat und ich für den Urlaub etwas kleineres wollte, legte ich mir einen Ersatz zu. Ergebnis: Es liegen 3 funktionierende Digitalkameras herum. Um die wieder gut funktionierende PowerShot nicht in der Ecke vergammeln zu lassen und mich schon länger Zeitraffer-Aufnahmen interessieren, beschloss ich, das Teil ein wenig umzubauen: = Fernauslöser für die PowerShot A95 = Das Fernauslösen der A95 ist zwar möglich, jedoch nur per PC und einer Software von Canon. Mit ihr können zwar auch Zeitraffer-Aufnahmen gemacht werden, allerdings ist es nicht besonders effizient und auch umständlich, den Computer zu transportieren bzw. tagelang laufen zu lassen. Eine weitere Möglichkeit der Fernauslösung existiert nicht, da weder Auslöser-Eingang noch eine modifizierte Firmware bzw. Erweiterung wie [http://chdk.wikia.com/wiki/CHDK CHDK] für die Kamera existiert. Also muss man selber für den Fernauslöser-Eingang sorgen. Die Peripherie rund um die Hauptplatine ist hauptsächlich in Flexprint (dieses Polyimid-Zeug) ausgeführt, das man nicht gerade mit einem Dachrinnenbrater bearbeiten sollte. Gleichzeitg sind die Leiterbahnen sehr fein und lassen sich manuell schlecht verfolgen. Hier hilft es, die verdächtigen Stellen zu fotografieren und die Leiterbahnen mit Bildbearbeitung zu markieren und verfolgen. Praktischerweise enden die für den Auslöser relevanten Leitungen an einer gut erreichbaren Stelle und sind gut lötbar. Mit Fädeldraht kontaktiert muss das Zeug nur noch von außen erreichbar werden. Zum Glück findet sich im Gehäuse noch ein freies Fleckchen: neben dem Stromanschluss ist genug Platz für eine Buchsenleiste im 1,27mm Rastermaß. Für diese muss lediglich die Gummiabdeckung der restlichen Buchsen weichen. Mit Epoxid-Kleber hält das Teil bombenfest und die Kamera sieht von außen fast normal aus. <gallery> Datei:Kameratimer_1.jpg|Oberseite der Kamera Datei:Kameratimer_2.jpg|Rückseite der Kamera Datei:Kameratimer_3.jpg|Drähte für halb und ganz gedrückten Auslöser Datei:Kameratimer_4.jpg|Masseanschluss </gallery> = Auslöser = {{Infobox AVR | Typ = ATtiny26 | Takt = 3,2768 | FuseH = F4 | FuseL = B7 }} Jetzt muss die Kamera "nur noch" ausgelöst werden. Schließlich wäre das Ziel verfehlt, wenn man den ganzen Tag mit Uhr neben der Knipse sitzen und aufs Knöpfchen drücken müsste. Diesen Job soll ein ATTiny26 übernehmen, dessen Speicher sich im Nachhinein als etwas knapp erwiesen hat. Um den AVR versammeln sich nur wenige Komponenten: Als Taktquelle dient ein 3,2768MHz Quarz, die Anzeige übernimmt ein 1x20 Character LCD und zur Eingabe dient ein Drehgeber mit Taster den ich mal aus einer HP-Knipse geschlachtet habe. Zum Auslösen selbst wird ein einfacher Optokoppler (Typ weitestgehend unbekannt) verwendet. Der Drehgeber hat einen Vorteil und gleichzeitig auch Nachteil: Eine Raste sind zwei Übergänge der Ausgänge. Dadurch wird die Software nicht kompatibel mit anderen Drehgebern. Vorteil: die Auswertung ist etwas kompakter. Das LCD wird (nach Anfangsschwierigkeiten mit einer anderen Bibliothek) mit dem großartigen Code von [http://www.jump.to/fleury Peter Fleury] angesteuert. == Bedienkonzept == Ohne gute Bedienbarkeit hilft der beste Code im Hintergrund nichts. Zugegebenermaßen muss man sich bei einer etwas besseren Eieruhr keine Gedanken über die Usability machen, ein klein bisschen Komfort sollte aber drin sein. Die Software kennt vier Menüpunkte: * Low-Zeit des Ausgangs (L) * High-Zeit des Ausgangs (H) * Anzahl der Schaltvorgänge (n) * Statusanzeige/Verbleibende Zeit zum Zustandswechsel (R) Die Dauer der High-Zeit ist für Langzeitbelichtungen im BULB-Modus (also deutlich über den maximalen 30 Sekunden – nur für Spiegelreflexen relevant) gedacht. Mit dem Drehgeber kann man im ersten Modus durch die verschiedenen Menüpunkte wechseln. Drückt man den Drehgeber, wechselt der Modus zur Stellenwahl. Hier kann man nun auswählen, welche Stelle des angezeigten Werts bearbeiten will. Nach einem weiteren Druck kann man dann durch Drehen den Wert erhöhen bzw. verringern. Die verschiedenen Modi rotieren momentan durch. Intuitiver wäre es meiner Meinung noch, wenn man zwischen Wahl der Stelle und Erhöhen/Verringern so lange hin und her wechselt, bis man nicht mehr "am Rädchen dreht". Damit man auch weiß was man macht, wir der aktuelle Modus per Symbol auf dem Display angezeigt. Neben dem Modussymbol wird angezeigt, ob der Timer aktuell läuft (Play-/Stopp-Symbol), da die Parameter auch während dem Laufen des Timers verändert werden können. Bei der Anzeige der verbleibenden Zeit zum Zustandswechsel wird zusätzlich die nächste Flanke (steigend oder fallend) angezeigt. == Software == Herzstück ist der Timer des AVRs, der eine Zeitbasis von 0.1 Sekunden schafft. Dies ist gleichzeitig auch die kleinste einstellbare Einheit. Im Timer-Interrupt wird die komplette Verarbeitung der Schaltzeiten und der Ausgabe übernommen. Das Benutzerinterfache ist komplett im (berüchtigten) Main-Loop untergebracht. Sämtliche Benutzereingaben werden gepollt. Um das Entprellen der Taster zu sparen ist der restliche Code bewusst *hust* ineffizient. == Aufbau == Ursprünglich sollte die Schaltung (aufgrund der geringen Komplexität) auf Lochraster aufgebaut werden. Nachdem ich sowieso ein paar Leiterplatten fertigen lassen wollte, kam das Layout eben noch dazu. <gallery> Bild:Kameratimer_sch.png|Stromlaufplan Bild:Kameratimer_brd.png|Board </gallery> Das verwendete Display hat seine Anschlüsse mit 2x7 Pins auf der linken Seite. Dementsprechend wurde die Anschlussbelegung am Mikrocontroller angepasst. Mit Stift- und Buchsenleiste ist der Abstand zwischen Platine und Display genau so, dass man die ICs sockeln kann. Leider passt der hohe Quarz nicht mehr stehend darunter (zumindest der, den ich da hatte). An zwei Stellen war noch etwas knobeln angesagt: Beim Anschluss der Kamera und des Drehgebers. Leider hatte ich mir beim Test auf dem Breadboard nicht aufgeschrieben, wo was war. Etwas hakelig war auch die Kontrastspannung – aus irgendwelchen Gründen habe ich auch nach längerem probieren keine vernünftige Widerstandskombination gefunden. Schlussendlich habe ich am Rand der Platine ein Poti angelötet. == Anschluss an die Kamera == [[Datei:Canon Klinke.png|thumb|Belegung des 2.5mm-Klinkensteckers für Canon-Fernauslöser]] Der Anschluss für die Kamera ist eine 2,5mm-Klinkenbuchse. Diese hat den Vorteil, dass man die kleineren Spiegelreflexen von Canon direkt mit einem einfachen Klinkenverbinder angeschlossen werden können. Am Fernauslösereingang der SLRs (zumindest an der EOS 400D) liegt eine Spannung von 3,3V an, beim Ziehen auf Masse wird je nach Pin entweder fokussiert oder ausgelöst. Zieht man den Pin zum Auslösen auf Masse, ohne zuvor zu fokussieren (oder auf manuellen Fokus eingestellt zu haben), holt dies die Kamera vor dem Auslösen nach, was den Vorgang verzögert. Dieses Verhalten habe ich bei der PowerShot nicht beobachten können. Wird nur die Leitung zum Auslösen auf Masse gezogen, passiert nichts. Werden beide Leitungen gleichzeitig auf Masse gezogen, löst die Kamera ohne Probleme aus. Um einen zusätzlichen Optokoppler zu sparen, habe ich die Fokussier- und Auslöseleitung im Timer verbunden. Das hat zur Folge, dass die Kamera, wenn sie am Timer angeschlossen ist, auch dann auslöst, wenn man den Auslöser nur halb drückt. Die Verschaltung scheint nach einem Blick auf die Innereien des [http://www.eosdoc.com/manuals/?q=RS-60E3 RS-60E3] üblich zu sein und sollte zu keinen Problemen führen. = Trivia = Die Software/Hardware hat mich ziemlich gefuchst. Aufgrund des Platzmangels war kein Debugging über UART möglich, Hardware für „richtiges“ Debugging ist leider auch nicht vorhanden. Ich habe bis heute nicht herausgefunden, woran sich der AVR gestört hat. Manchmal funktionierte das Teil, manchmal auch nach dem 10. Mal einschalten noch nicht. Auch ein nachträglicher Reset brachte nichts – es war wie verhext. Es war kein offensichtlicher Hard- oder Softwarefehler zu finden. Eines ist sicher: Nie wieder Smileys auf einem Layout. Die Probleme waren auch der Grund dafür, warum ich das Projektchen erst fast ein Jahr nach dem eigentlichen Aufbau dokumentiere. = Tipps für Aufnahmen = Beim ersten Test musste eine Amaryllis herhalten. Aus dem Versuch kommen folgende Erkenntnisse: * Energiesparlampen sind trotz Weißabgleich für die Beleuchtung ungeeignet * Bildausschnitt immer großzügig wählen, zuschneiden kann man später immer noch * Manuellen Fokus verwenden ** Geringere Auslöseverzögerung ** Vermeidung wandern der Schärfeebene ** Schärfenebene so einstellen, damit zum Schluss auch das Interessante scharf ist * Bei der Aufnahmedauer, dem Intervall und dem damit verbundenen Speicherplatzbedarf lieber zweimal rechnen * Bildnummerierung vor der Aufnahme zurücksetzen [[Datei:Kameratimer_schnuller.JPG|thumb|"Stromspar"-Stecker]] Leider löschen die ganzen kompakten Canons den AF-Lock, sobald das Display abgeschaltet wird. Mit einem kleinen Trick kann man das Display abschalten, ohne die Aufnahmeparameter zu beeinflussen: Steckt man eine 3,5mm-Klinke in den Videoausgang, wird das interne Display abgeschaltet. Der Bildsensor bleibt bei diesem „Trick“ jedoch aktiv, was eine deutlich höhere Stromaufnahme im Gegensatz zum Standby-Modus bedeutet. Bei einer zweiten Testaufnahme eines Sonnenuntergangs habe ich festgestellt, dass die automatische Belichtungssteuerung erstaunlich „geschmeidig“ arbeitet. Unter den knapp 400 Fotos waren trotz kurzzeitigem Gegenlicht keine Ausreißer. Als Warnung sei noch angebracht, dass Bildsensoren nicht unbedingt dafür ausgelegt sind, längerer Zeit direkte Sonneneinstrahlung auszuhalten. Auf gut Deutsch: Wenn man einen Zeitraffer von der Sonne macht, kann mit dem Bildsensor dasselbe wie Ameisen passieren, die mit der Lupe brutzelt. = Download = [[Datei:Kameratimer.zip]] 47d50392bfc7fb3ab6dd48888afba6f74727d22c EMR7370 0 287 732 719 2012-03-15T21:34:36Z Chris 2 /* Datenanalyse */ wikitext text/x-wiki [[Datei:EMR7370_aussen.jpg|thumb|Empfänger]] Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade. Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch. =Schaltungsanalyse= Der erste Schritt zur Analyse des Ganzen führt natürlich über den Schraubendreher. Im Inneren befindet sich eine große Leiterplatte, auf der eine kleinere Huckepack sitzt. Da an dieser eine Antenne angelötet ist, ist der Funkempfänger schnell gefunden. Der Silkscreen verrät sogar die Anschlussbelegung desselben. Nachdem bei der ersten Untersuchung die Hälfte der Beschriftung durch das Modul verdeckt war, habe ich diese nochmal weiter oben angebracht, deswegen bitte nicht wundern. Auch die Buchsen- & Stiftleiste sind nicht original, sondern von mir hinzugefügt. Da die andere Seite der Leiterplatte nicht spektakulärer ist, habe ich auf ein Foto verzichtet. Das einzig halbwegs interessante ist ein I²C-EEPROM, dessen Takt- und Datenleitung an der Stiftleiste liegt. <gallery> Datei:EMR7370_bottom.jpg|Platinenunterseite Datei:EMR7370_RXM01.jpg|Funkmodul RXM01 </gallery> Zu dem Funkmodul konnte ich im Internet nur die Bestätigung über die Existenz finden, wobei dort selbst die Angabe der Betriebsspannung unterschiedlich war. =Protokollanalyse= Da die Leiterplatte mit den Bezeichnungen SCK/SDI/SDO/NSEL schon auf SPI hindeutet wusste ich ungefähr, worauf ich mich einlasse. Mit der Stift- und Buchsenleiste zwischen Funkmodul und Hauptplatine sollte es relativ einfach sein, auf dem untersten Layer (Bitübertragungsschicht, wenn man es an dieser Stelle so nennen will) zu analysieren. Also Probes angeschlossen und gleich mal den neuen Logic Analyzer getestet. Die erste Messung zeigt die übertragenen Daten vom Einschalten des Empfängers bis zur ersten Anzeige der Messwerte. Genauer betrachtet und mit aktiviertem SPI-Analyzer sieht man auch, was übertragen wird: <gallery> EMR7370_LA1.png|Übersicht EMR7370_LA2.png|Zoom auf den ersten Block </gallery> Zur mutmaßlichen Initialisierung werden folgende Daten übertragen: <pre> 0x90D9 0xA67C 0xC080 0xC081 (500ms Pause) 0xCE85 0xCE87 0xC4AB 0xC823 0xC6C7 0xB014 0xC205 0xC080 (188ms Pause) 0xC081 (4ms Pause) 0x94D9 0xC209 (5ms Pause) 0x00 0x90D9 0xC080 (52ms Pause) 0xC081 </pre> Auch nach dem Empfang eines Datenpaketes sendet die Elektronik noch ein paar Päckchen an den Empfänger: </pre> 0xCE85 0xC080 (längere Pause) 0xC081 (3ms Pause) 0xCE85 0xCE87 </pre> Hier fällt auf, dass 0xC080 und 0xC081 oft in Kombination (siehe auch oben) und vor allem in der Nähe eines Datenempfangs auftreten. Ob dahinter eine Kausalität steckt?!? Da ich mich schon einmal kurzzeitig mit Funkmodule aus dem Hause HopeRF auseinandergesetzt habe und deren Produkte eine ähnliche Bezeichnung haben (z. B. RFM01), habe ich auf gut Glück auf deren Homepage nochmal vorbei geschaut. Wie durch meine vorherige Recherche erwartet, fand ich nichts, was genauso hieß oder aussah wie mein Funkmodul, allerdings blieb ich kurz am Datenblatt des RFM01 hängen. Nachdem ich ein paar der Befehle in Hex umrechnete, stellte sich ein deutlicher Wiedererkennungswert heraus! Alle (bis auf einen) der gesendeten Datensätze ließ sich sinnvoll durch die Inhalte des Datenblatts rekonstruieren - also ein voller Erfolg. Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht. =Datenanalyse= Für die Datenanalyse erzeugte ich mir durch eine definierte Last (vulgo: Glühlampe) Werte, die ich in Excel zwischen den gesendeten und auf dem EMR angezeigten Werten abglich. Hier eine kleine Tabelle einiger Werte: {| class="wikitable sortable" |- ! U !! I !! P !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 !! 9 !! 10 !! 11 |- | 221,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 06 || BB || 40 || 00 || F4 |- | 221,5 || 0,17 || 39,0 || 25 || 6A || 54 || 72 || 40 || 4E || 00 || B1 || BB || 40 || 00 || 71 |- | 222,5 || 0,17 || 39,5 || 25 || 6A || 54 || 72 || 40 || 4F || 00 || B2 || BD || 40 || 01 || 6C |- | 222,5 || 0,06 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 43 || BD || 40 || 01 || 25 |- | 223,0 || 0,03 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 25 || BE || 40 || 01 || 42 |- | 222,0 || 0,03 || 2,0 || 25 || 6A || 54 || 72 || 40 || 04 || 00 || 20 || BC || 40 || 01 || 4A |- | 222,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3E || BD || 40 || 01 || 2D |- | 223,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3C || BF || 40 || 01 || 2D |- | 222,5 || 0,31 || 29,0 || 25 || 6A || 54 || 72 || 40 || 3A || 01 || 3E || BD || 40 || 01 || F4 |- | 222,0 || 0,37 || 42,0 || 25 || 6A || 54 || 72 || 40 || 54 || 01 || 74 || BC || 40 || 01 || A5 |- | 223,0 || 0,35 || 42,5 || 25 || 6A || 54 || 72 || 40 || 55 || 01 || 66 || BE || 40 || 02 || AF |- | 221,5 || 0,19 || 38,0 || 25 || 6A || 54 || 72 || 40 || 4C || 00 || BF || BB || 40 || 02 || 63 |- | 224,0 || 0,13 || 12,5 || 25 || 6A || 54 || 72 || 40 || 19 || 00 || 8B || C0 || 40 || 03 || C4 |- | 220,5 || 0,02 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 1A || B9 || 40 || 04 || 52 |} Die ersten drei Spalten geben die Spannung in Volt, den Strom in Ampere sowie die Leistung in Watt an, alle weiteren die empfangenen Bytes im Hex-Format. Ziel der Tabelle ist es, Muster zu erkennen und die Bytes den Werten zuzuordnen. Dabei hilft es natürlich Messungen zu erzeugen, bei dem möglichst viele Werte konstant sind und sich nur einer verändert. Beim Strom bzw. der Leistung klappt das gut, bei der Spannung ist man ohne Trenntransformator etwas auf Netzschwankungen angewiesen. Wer es selber einmal probieren will, kann die Tabelle mit einem Klick auf die Spaltenköpfe sortieren. Sortiert man z. B. nach der Spannung sieht man relativ schnell, dass diese einen Zusammenhang mit Spalte 8 hat. Anhand der übertragenen und der abgelesenen Werte kann man nun den Zusammenhang ermitteln. In der Regel ist dieser sehr einfach zu berechnen, solange er linear ist. Mathematisch kann man die Formel :<math> x=a \cdot y + b </math> in einem Gleichungssystem mit den verschiedenen Werten einsetzen, wobei x der gemessenen Spannung und y dem übertragenen Wert entspricht - was natürlich auch anders herum funktioniert. Mit ein wenig Zahlengefühl muss man keine Gleichungssysteme lösen. Nimmt man die Spannungen 222,0V 222,5V und 223V und die korrespondierenden Werte 0xBC, 0xBD und 0xBE (bzw. den dezimalen Entsprechungen 188, 189 und 190) sieht man, dass die Nachkommastelle der niederwertigsten Stelle entspricht. Teilt man durch 2, bekommt man 94; 94,5 und 95 - die Differenz zu den abgelesenen Spannungen entspricht 128. Das passt auch für alle anderen Werte. d27f766860b13de3985fc3bed89077caca35e6ad 734 732 2012-03-15T21:56:03Z Chris 2 /* Protokollanalyse */ wikitext text/x-wiki [[Datei:EMR7370_aussen.jpg|thumb|Empfänger]] Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade. Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch. =Schaltungsanalyse= Der erste Schritt zur Analyse des Ganzen führt natürlich über den Schraubendreher. Im Inneren befindet sich eine große Leiterplatte, auf der eine kleinere Huckepack sitzt. Da an dieser eine Antenne angelötet ist, ist der Funkempfänger schnell gefunden. Der Silkscreen verrät sogar die Anschlussbelegung desselben. Nachdem bei der ersten Untersuchung die Hälfte der Beschriftung durch das Modul verdeckt war, habe ich diese nochmal weiter oben angebracht, deswegen bitte nicht wundern. Auch die Buchsen- & Stiftleiste sind nicht original, sondern von mir hinzugefügt. Da die andere Seite der Leiterplatte nicht spektakulärer ist, habe ich auf ein Foto verzichtet. Das einzig halbwegs interessante ist ein I²C-EEPROM, dessen Takt- und Datenleitung an der Stiftleiste liegt. <gallery> Datei:EMR7370_bottom.jpg|Platinenunterseite Datei:EMR7370_RXM01.jpg|Funkmodul RXM01 </gallery> Zu dem Funkmodul konnte ich im Internet nur die Bestätigung über die Existenz finden, wobei dort selbst die Angabe der Betriebsspannung unterschiedlich war. =Protokollanalyse= Da die Leiterplatte mit den Bezeichnungen SCK/SDI/SDO/NSEL schon auf SPI hindeutet wusste ich ungefähr, worauf ich mich einlasse. Mit der Stift- und Buchsenleiste zwischen Funkmodul und Hauptplatine sollte es relativ einfach sein, auf dem untersten Layer (Bitübertragungsschicht, wenn man es an dieser Stelle so nennen will) zu analysieren. Also Probes angeschlossen und gleich mal den neuen Logic Analyzer getestet. Die erste Messung zeigt die übertragenen Daten vom Einschalten des Empfängers bis zur ersten Anzeige der Messwerte. Genauer betrachtet und mit aktiviertem SPI-Analyzer sieht man auch, was übertragen wird: <gallery> EMR7370_LA1.png|Übersicht EMR7370_LA2.png|Zoom auf den ersten Block </gallery> Zur mutmaßlichen Initialisierung werden folgende Daten übertragen: <pre> 0x90D9 0xA67C 0xC080 0xC081 (500ms Pause) 0xCE85 0xCE87 0xC4AB 0xC823 0xC6C7 0xB014 0xC205 0xC080 (188ms Pause) 0xC081 (4ms Pause) 0x94D9 0xC209 (5ms Pause) 0x00 0x90D9 0xC080 (52ms Pause) 0xC081 </pre> Auch nach dem Empfang eines Datenpaketes sendet die Elektronik noch ein paar Päckchen an den Empfänger: </pre> 0xCE85 0xC080 (längere Pause) 0xC081 (3ms Pause) 0xCE85 0xCE87 </pre> Hier fällt auf, dass 0xC080 und 0xC081 oft in Kombination (siehe auch oben) und vor allem in der Nähe eines Datenempfangs auftreten. Ob dahinter ein Zusammenhang steckt?!? Da ich mich schon einmal kurzzeitig mit Funkmodule aus dem Hause HopeRF auseinandergesetzt habe und deren Produkte eine ähnliche Bezeichnung haben (z. B. RFM01), habe ich auf gut Glück auf deren Homepage nochmal vorbeigeschaut. Wie durch meine vorherige Recherche erwartet, fand ich nichts, was genauso hieß oder aussah wie mein Funkmodul, allerdings blieb ich kurz am Datenblatt des RFM01 hängen. Nachdem ich ein paar der Befehle in Hex umrechnete, stellte sich ein deutlicher Wiedererkennungswert heraus! Alle (bis auf einen) der gesendeten Datensätze ließen sich sinnvoll durch die Inhalte des Datenblatts rekonstruieren - also ein voller Erfolg. Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht. [[Datei:EMR7370_LA3.png|thumb|Datenempfang (großer Monitor erforderlich)]] Die eigentliche Datenübertragung wird durch das Interrupt-Signal NIRQ angestoßen. Das N deutet auf "negative", also einer negativen Flanke hin, was auch der Messung entspricht. Nach dem Interrupt muss zunächst ein Nibble gelesen werden, das den Datenempfang signalisiert. Anschließend kann ein vollständiges Byte an SDO (Serial Data Out - aus Sicht de Funkmoduls) bzw. MISO (Master In Slave Out) eingelesen werden. Da die Schnittstelle bitseriell ist, ist auch die Flanke sowie die Reihenfolge der Bits wichtig. In diesem Fall wird zur steigenden Flanke von SCK (Serial Clock) gelesen, während sich die Daten zur fallenden Flanke ändern. Auch wird hier das MSB (Most Significant Bit) zuerst übertragen (was auch der üblichen Leseweise von Bits entspricht). Anzumerken ist bei dem Empfänger, dass man wissen muss, wie viele Byte empfangen werden sollen. Hier sind schon sehr viele (inklusive mir) hereingefallen. Sofern das Modul dem Verhalten derer von HopeRF entspricht, wird die Übertragung durch ein Synchronisationswort angestoßen, aber nicht signalisiert, wann die Übertragung zu Ende ist. Heißt: Der Empfänger weiß zwar, wann der Sender angefangen hat, aber nicht, wann er wieder aufhört. Das ist dann Protokollsache. Weiß man also nicht, wann das Paket zu Ende ist, wird man es im dümmsten Fall auch nie merken, da der Empfänger einfach das Rauschen auf dem Kanal auswertet. Das dient aber aller höchstens als Zufallsgenerator. Wie unten in der Tabelle zu sehen, umfassen die Pakete eine Länge von 12 Bytes. Danach muss man selber den Empfänger zum Schweigen bringen bzw. zurücksetzen. =Datenanalyse= Für die Datenanalyse erzeugte ich mir durch eine definierte Last (vulgo: Glühlampe) Werte, die ich in Excel zwischen den gesendeten und auf dem EMR angezeigten Werten abglich. Hier eine kleine Tabelle einiger Werte: {| class="wikitable sortable" |- ! U !! I !! P !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 !! 9 !! 10 !! 11 |- | 221,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 06 || BB || 40 || 00 || F4 |- | 221,5 || 0,17 || 39,0 || 25 || 6A || 54 || 72 || 40 || 4E || 00 || B1 || BB || 40 || 00 || 71 |- | 222,5 || 0,17 || 39,5 || 25 || 6A || 54 || 72 || 40 || 4F || 00 || B2 || BD || 40 || 01 || 6C |- | 222,5 || 0,06 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 43 || BD || 40 || 01 || 25 |- | 223,0 || 0,03 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 25 || BE || 40 || 01 || 42 |- | 222,0 || 0,03 || 2,0 || 25 || 6A || 54 || 72 || 40 || 04 || 00 || 20 || BC || 40 || 01 || 4A |- | 222,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3E || BD || 40 || 01 || 2D |- | 223,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3C || BF || 40 || 01 || 2D |- | 222,5 || 0,31 || 29,0 || 25 || 6A || 54 || 72 || 40 || 3A || 01 || 3E || BD || 40 || 01 || F4 |- | 222,0 || 0,37 || 42,0 || 25 || 6A || 54 || 72 || 40 || 54 || 01 || 74 || BC || 40 || 01 || A5 |- | 223,0 || 0,35 || 42,5 || 25 || 6A || 54 || 72 || 40 || 55 || 01 || 66 || BE || 40 || 02 || AF |- | 221,5 || 0,19 || 38,0 || 25 || 6A || 54 || 72 || 40 || 4C || 00 || BF || BB || 40 || 02 || 63 |- | 224,0 || 0,13 || 12,5 || 25 || 6A || 54 || 72 || 40 || 19 || 00 || 8B || C0 || 40 || 03 || C4 |- | 220,5 || 0,02 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 1A || B9 || 40 || 04 || 52 |} Die ersten drei Spalten geben die Spannung in Volt, den Strom in Ampere sowie die Leistung in Watt an, alle weiteren die empfangenen Bytes im Hex-Format. Ziel der Tabelle ist es, Muster zu erkennen und die Bytes den Werten zuzuordnen. Dabei hilft es natürlich Messungen zu erzeugen, bei dem möglichst viele Werte konstant sind und sich nur einer verändert. Beim Strom bzw. der Leistung klappt das gut, bei der Spannung ist man ohne Trenntransformator etwas auf Netzschwankungen angewiesen. Wer es selber einmal probieren will, kann die Tabelle mit einem Klick auf die Spaltenköpfe sortieren. Sortiert man z. B. nach der Spannung sieht man relativ schnell, dass diese einen Zusammenhang mit Spalte 8 hat. Anhand der übertragenen und der abgelesenen Werte kann man nun den Zusammenhang ermitteln. In der Regel ist dieser sehr einfach zu berechnen, solange er linear ist. Mathematisch kann man die Formel :<math> x=a \cdot y + b </math> in einem Gleichungssystem mit den verschiedenen Werten einsetzen, wobei x der gemessenen Spannung und y dem übertragenen Wert entspricht - was natürlich auch anders herum funktioniert. Mit ein wenig Zahlengefühl muss man keine Gleichungssysteme lösen. Nimmt man die Spannungen 222,0V 222,5V und 223V und die korrespondierenden Werte 0xBC, 0xBD und 0xBE (bzw. den dezimalen Entsprechungen 188, 189 und 190) sieht man, dass die Nachkommastelle der niederwertigsten Stelle entspricht. Teilt man durch 2, bekommt man 94; 94,5 und 95 - die Differenz zu den abgelesenen Spannungen entspricht 128. Das passt auch für alle anderen Werte. b4760454c4dc37bbb6a3c3a0807be238771bc7c8 735 734 2012-03-15T21:56:54Z Chris 2 wikitext text/x-wiki [[Datei:EMR7370_aussen.jpg|thumb|Empfänger]] Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade. Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch. =Schaltungsanalyse= Der erste Schritt zur Analyse des Ganzen führt natürlich über den Schraubendreher. Im Inneren befindet sich eine große Leiterplatte, auf der eine kleinere Huckepack sitzt. Da an dieser eine Antenne angelötet ist, ist der Funkempfänger schnell gefunden. Der Silkscreen verrät sogar die Anschlussbelegung desselben. Nachdem bei der ersten Untersuchung die Hälfte der Beschriftung durch das Modul verdeckt war, habe ich diese nochmal weiter oben angebracht, deswegen bitte nicht wundern. Auch die Buchsen- & Stiftleiste sind nicht original, sondern von mir hinzugefügt. Da die andere Seite der Leiterplatte nicht spektakulärer ist, habe ich auf ein Foto verzichtet. Das einzig halbwegs interessante ist ein I²C-EEPROM, dessen Takt- und Datenleitung an der Stiftleiste liegt. <gallery> Datei:EMR7370_bottom.jpg|Platinenunterseite Datei:EMR7370_RXM01.jpg|Funkmodul RXM01 </gallery> Zu dem Funkmodul konnte ich im Internet nur die Bestätigung über die Existenz finden, wobei dort selbst die Angabe der Betriebsspannung unterschiedlich war. =Protokollanalyse= Da die Leiterplatte mit den Bezeichnungen SCK/SDI/SDO/NSEL schon auf SPI hindeutet wusste ich ungefähr, worauf ich mich einlasse. Mit der Stift- und Buchsenleiste zwischen Funkmodul und Hauptplatine sollte es relativ einfach sein, auf dem untersten Layer (Bitübertragungsschicht, wenn man es an dieser Stelle so nennen will) zu analysieren. Also Probes angeschlossen und gleich mal den neuen Logic Analyzer getestet. Die erste Messung zeigt die übertragenen Daten vom Einschalten des Empfängers bis zur ersten Anzeige der Messwerte. Genauer betrachtet und mit aktiviertem SPI-Analyzer sieht man auch, was übertragen wird: <gallery> EMR7370_LA1.png|Übersicht EMR7370_LA2.png|Zoom auf den ersten Block </gallery> Zur mutmaßlichen Initialisierung werden folgende Daten übertragen: <pre> 0x90D9 0xA67C 0xC080 0xC081 (500ms Pause) 0xCE85 0xCE87 0xC4AB 0xC823 0xC6C7 0xB014 0xC205 0xC080 (188ms Pause) 0xC081 (4ms Pause) 0x94D9 0xC209 (5ms Pause) 0x00 0x90D9 0xC080 (52ms Pause) 0xC081 </pre> Auch nach dem Empfang eines Datenpaketes sendet die Elektronik noch ein paar Päckchen an den Empfänger: </pre> 0xCE85 0xC080 (längere Pause) 0xC081 (3ms Pause) 0xCE85 0xCE87 </pre> Hier fällt auf, dass 0xC080 und 0xC081 oft in Kombination (siehe auch oben) und vor allem in der Nähe eines Datenempfangs auftreten. Ob dahinter ein Zusammenhang steckt?!? Da ich mich schon einmal kurzzeitig mit Funkmodule aus dem Hause HopeRF auseinandergesetzt habe und deren Produkte eine ähnliche Bezeichnung haben (z. B. RFM01), habe ich auf gut Glück auf deren Homepage nochmal vorbeigeschaut. Wie durch meine vorherige Recherche erwartet, fand ich nichts, was genauso hieß oder aussah wie mein Funkmodul, allerdings blieb ich kurz am Datenblatt des RFM01 hängen. Nachdem ich ein paar der Befehle in Hex umrechnete, stellte sich ein deutlicher Wiedererkennungswert heraus! Alle (bis auf einen) der gesendeten Datensätze ließen sich sinnvoll durch die Inhalte des Datenblatts rekonstruieren - also ein voller Erfolg. Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht. [[Datei:EMR7370_LA3.png|thumb|Datenempfang (großer Monitor erforderlich)]] Die eigentliche Datenübertragung wird durch das Interrupt-Signal NIRQ angestoßen. Das N deutet auf "negative", also einer negativen Flanke hin, was auch der Messung entspricht. Nach dem Interrupt muss zunächst ein Nibble gelesen werden, das den Datenempfang signalisiert. Anschließend kann ein vollständiges Byte an SDO (Serial Data Out - aus Sicht de Funkmoduls) bzw. MISO (Master In Slave Out) eingelesen werden. Da die Schnittstelle bitseriell ist, ist auch die Flanke sowie die Reihenfolge der Bits wichtig. In diesem Fall wird zur steigenden Flanke von SCK (Serial Clock) gelesen, während sich die Daten zur fallenden Flanke ändern. Auch wird hier das MSB (Most Significant Bit) zuerst übertragen (was auch der üblichen Leseweise von Bits entspricht). Anzumerken ist bei dem Empfänger, dass man wissen muss, wie viele Byte empfangen werden sollen. Hier sind schon sehr viele (inklusive mir) hereingefallen. Sofern das Modul dem Verhalten derer von HopeRF entspricht, wird die Übertragung durch ein Synchronisationswort angestoßen, aber nicht signalisiert, wann die Übertragung zu Ende ist. Heißt: Der Empfänger weiß zwar, wann der Sender angefangen hat, aber nicht, wann er wieder aufhört. Das ist dann Protokollsache. Weiß man also nicht, wann das Paket zu Ende ist, wird man es im dümmsten Fall auch nie merken, da der Empfänger einfach das Rauschen auf dem Kanal auswertet. Das dient aber aller höchstens als Zufallsgenerator. Wie unten in der Tabelle zu sehen, umfassen die Pakete eine Länge von 12 Bytes. Danach muss man selber den Empfänger zum Schweigen bringen bzw. zurücksetzen. =Datenanalyse= Für die Datenanalyse erzeugte ich mir durch eine definierte Last (vulgo: Glühlampe) Werte, die ich in Excel zwischen den gesendeten und auf dem EMR angezeigten Werten abglich. Hier eine kleine Tabelle einiger Werte: {| class="wikitable sortable" |- ! U !! I !! P !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 !! 9 !! 10 !! 11 |- | 221,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 06 || BB || 40 || 00 || F4 |- | 221,5 || 0,17 || 39,0 || 25 || 6A || 54 || 72 || 40 || 4E || 00 || B1 || BB || 40 || 00 || 71 |- | 222,5 || 0,17 || 39,5 || 25 || 6A || 54 || 72 || 40 || 4F || 00 || B2 || BD || 40 || 01 || 6C |- | 222,5 || 0,06 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 43 || BD || 40 || 01 || 25 |- | 223,0 || 0,03 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 25 || BE || 40 || 01 || 42 |- | 222,0 || 0,03 || 2,0 || 25 || 6A || 54 || 72 || 40 || 04 || 00 || 20 || BC || 40 || 01 || 4A |- | 222,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3E || BD || 40 || 01 || 2D |- | 223,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3C || BF || 40 || 01 || 2D |- | 222,5 || 0,31 || 29,0 || 25 || 6A || 54 || 72 || 40 || 3A || 01 || 3E || BD || 40 || 01 || F4 |- | 222,0 || 0,37 || 42,0 || 25 || 6A || 54 || 72 || 40 || 54 || 01 || 74 || BC || 40 || 01 || A5 |- | 223,0 || 0,35 || 42,5 || 25 || 6A || 54 || 72 || 40 || 55 || 01 || 66 || BE || 40 || 02 || AF |- | 221,5 || 0,19 || 38,0 || 25 || 6A || 54 || 72 || 40 || 4C || 00 || BF || BB || 40 || 02 || 63 |- | 224,0 || 0,13 || 12,5 || 25 || 6A || 54 || 72 || 40 || 19 || 00 || 8B || C0 || 40 || 03 || C4 |- | 220,5 || 0,02 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 1A || B9 || 40 || 04 || 52 |} Die ersten drei Spalten geben die Spannung in Volt, den Strom in Ampere sowie die Leistung in Watt an, alle weiteren die empfangenen Bytes im Hex-Format. Ziel der Tabelle ist es, Muster zu erkennen und die Bytes den Werten zuzuordnen. Dabei hilft es natürlich Messungen zu erzeugen, bei dem möglichst viele Werte konstant sind und sich nur einer verändert. Beim Strom bzw. der Leistung klappt das gut, bei der Spannung ist man ohne Trenntransformator etwas auf Netzschwankungen angewiesen. Wer es selber einmal probieren will, kann die Tabelle mit einem Klick auf die Spaltenköpfe sortieren. Sortiert man z. B. nach der Spannung sieht man relativ schnell, dass diese einen Zusammenhang mit Spalte 8 hat. Anhand der übertragenen und der abgelesenen Werte kann man nun den Zusammenhang ermitteln. In der Regel ist dieser sehr einfach zu berechnen, solange er linear ist. Mathematisch kann man die Formel <math> x=a \cdot y + b </math> in einem Gleichungssystem mit den verschiedenen Werten einsetzen, wobei x der gemessenen Spannung und y dem übertragenen Wert entspricht - was natürlich auch anders herum funktioniert. Mit ein wenig Zahlengefühl muss man keine Gleichungssysteme lösen. Nimmt man die Spannungen 222,0V 222,5V und 223V und die korrespondierenden Werte 0xBC, 0xBD und 0xBE (bzw. den dezimalen Entsprechungen 188, 189 und 190) sieht man, dass die Nachkommastelle der niederwertigsten Stelle entspricht. Teilt man durch 2, bekommt man 94; 94,5 und 95 - die Differenz zu den abgelesenen Spannungen entspricht 128. Das passt auch für alle anderen Werte. 9795259e71000fd99ebfa1f2c6e6bfc2bbce52ed 736 735 2012-03-15T21:57:58Z Chris 2 /* Protokollanalyse */ Abschnitte eingefügt wikitext text/x-wiki [[Datei:EMR7370_aussen.jpg|thumb|Empfänger]] Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade. Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch. =Schaltungsanalyse= Der erste Schritt zur Analyse des Ganzen führt natürlich über den Schraubendreher. Im Inneren befindet sich eine große Leiterplatte, auf der eine kleinere Huckepack sitzt. Da an dieser eine Antenne angelötet ist, ist der Funkempfänger schnell gefunden. Der Silkscreen verrät sogar die Anschlussbelegung desselben. Nachdem bei der ersten Untersuchung die Hälfte der Beschriftung durch das Modul verdeckt war, habe ich diese nochmal weiter oben angebracht, deswegen bitte nicht wundern. Auch die Buchsen- & Stiftleiste sind nicht original, sondern von mir hinzugefügt. Da die andere Seite der Leiterplatte nicht spektakulärer ist, habe ich auf ein Foto verzichtet. Das einzig halbwegs interessante ist ein I²C-EEPROM, dessen Takt- und Datenleitung an der Stiftleiste liegt. <gallery> Datei:EMR7370_bottom.jpg|Platinenunterseite Datei:EMR7370_RXM01.jpg|Funkmodul RXM01 </gallery> Zu dem Funkmodul konnte ich im Internet nur die Bestätigung über die Existenz finden, wobei dort selbst die Angabe der Betriebsspannung unterschiedlich war. =Protokollanalyse= Da die Leiterplatte mit den Bezeichnungen SCK/SDI/SDO/NSEL schon auf SPI hindeutet wusste ich ungefähr, worauf ich mich einlasse. Mit der Stift- und Buchsenleiste zwischen Funkmodul und Hauptplatine sollte es relativ einfach sein, auf dem untersten Layer (Bitübertragungsschicht, wenn man es an dieser Stelle so nennen will) zu analysieren. Also Probes angeschlossen und gleich mal den neuen Logic Analyzer getestet. Die erste Messung zeigt die übertragenen Daten vom Einschalten des Empfängers bis zur ersten Anzeige der Messwerte. Genauer betrachtet und mit aktiviertem SPI-Analyzer sieht man auch, was übertragen wird: <gallery> EMR7370_LA1.png|Übersicht EMR7370_LA2.png|Zoom auf den ersten Block </gallery> == Initialisierung == Zur mutmaßlichen Initialisierung werden folgende Daten übertragen: <pre> 0x90D9 0xA67C 0xC080 0xC081 (500ms Pause) 0xCE85 0xCE87 0xC4AB 0xC823 0xC6C7 0xB014 0xC205 0xC080 (188ms Pause) 0xC081 (4ms Pause) 0x94D9 0xC209 (5ms Pause) 0x00 0x90D9 0xC080 (52ms Pause) 0xC081 </pre> Auch nach dem Empfang eines Datenpaketes sendet die Elektronik noch ein paar Päckchen an den Empfänger: </pre> 0xCE85 0xC080 (längere Pause) 0xC081 (3ms Pause) 0xCE85 0xCE87 </pre> Hier fällt auf, dass 0xC080 und 0xC081 oft in Kombination (siehe auch oben) und vor allem in der Nähe eines Datenempfangs auftreten. Ob dahinter ein Zusammenhang steckt?!? Da ich mich schon einmal kurzzeitig mit Funkmodule aus dem Hause HopeRF auseinandergesetzt habe und deren Produkte eine ähnliche Bezeichnung haben (z. B. RFM01), habe ich auf gut Glück auf deren Homepage nochmal vorbeigeschaut. Wie durch meine vorherige Recherche erwartet, fand ich nichts, was genauso hieß oder aussah wie mein Funkmodul, allerdings blieb ich kurz am Datenblatt des RFM01 hängen. Nachdem ich ein paar der Befehle in Hex umrechnete, stellte sich ein deutlicher Wiedererkennungswert heraus! Alle (bis auf einen) der gesendeten Datensätze ließen sich sinnvoll durch die Inhalte des Datenblatts rekonstruieren - also ein voller Erfolg. Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht. ==Datenpaket== [[Datei:EMR7370_LA3.png|thumb|Datenempfang (großer Monitor erforderlich)]] Die eigentliche Datenübertragung wird durch das Interrupt-Signal NIRQ angestoßen. Das N deutet auf "negative", also einer negativen Flanke hin, was auch der Messung entspricht. Nach dem Interrupt muss zunächst ein Nibble gelesen werden, das den Datenempfang signalisiert. Anschließend kann ein vollständiges Byte an SDO (Serial Data Out - aus Sicht de Funkmoduls) bzw. MISO (Master In Slave Out) eingelesen werden. Da die Schnittstelle bitseriell ist, ist auch die Flanke sowie die Reihenfolge der Bits wichtig. In diesem Fall wird zur steigenden Flanke von SCK (Serial Clock) gelesen, während sich die Daten zur fallenden Flanke ändern. Auch wird hier das MSB (Most Significant Bit) zuerst übertragen (was auch der üblichen Leseweise von Bits entspricht). Anzumerken ist bei dem Empfänger, dass man wissen muss, wie viele Byte empfangen werden sollen. Hier sind schon sehr viele (inklusive mir) hereingefallen. Sofern das Modul dem Verhalten derer von HopeRF entspricht, wird die Übertragung durch ein Synchronisationswort angestoßen, aber nicht signalisiert, wann die Übertragung zu Ende ist. Heißt: Der Empfänger weiß zwar, wann der Sender angefangen hat, aber nicht, wann er wieder aufhört. Das ist dann Protokollsache. Weiß man also nicht, wann das Paket zu Ende ist, wird man es im dümmsten Fall auch nie merken, da der Empfänger einfach das Rauschen auf dem Kanal auswertet. Das dient aber aller höchstens als Zufallsgenerator. Wie unten in der Tabelle zu sehen, umfassen die Pakete eine Länge von 12 Bytes. Danach muss man selber den Empfänger zum Schweigen bringen bzw. zurücksetzen. =Datenanalyse= Für die Datenanalyse erzeugte ich mir durch eine definierte Last (vulgo: Glühlampe) Werte, die ich in Excel zwischen den gesendeten und auf dem EMR angezeigten Werten abglich. Hier eine kleine Tabelle einiger Werte: {| class="wikitable sortable" |- ! U !! I !! P !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 !! 9 !! 10 !! 11 |- | 221,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 06 || BB || 40 || 00 || F4 |- | 221,5 || 0,17 || 39,0 || 25 || 6A || 54 || 72 || 40 || 4E || 00 || B1 || BB || 40 || 00 || 71 |- | 222,5 || 0,17 || 39,5 || 25 || 6A || 54 || 72 || 40 || 4F || 00 || B2 || BD || 40 || 01 || 6C |- | 222,5 || 0,06 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 43 || BD || 40 || 01 || 25 |- | 223,0 || 0,03 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 25 || BE || 40 || 01 || 42 |- | 222,0 || 0,03 || 2,0 || 25 || 6A || 54 || 72 || 40 || 04 || 00 || 20 || BC || 40 || 01 || 4A |- | 222,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3E || BD || 40 || 01 || 2D |- | 223,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3C || BF || 40 || 01 || 2D |- | 222,5 || 0,31 || 29,0 || 25 || 6A || 54 || 72 || 40 || 3A || 01 || 3E || BD || 40 || 01 || F4 |- | 222,0 || 0,37 || 42,0 || 25 || 6A || 54 || 72 || 40 || 54 || 01 || 74 || BC || 40 || 01 || A5 |- | 223,0 || 0,35 || 42,5 || 25 || 6A || 54 || 72 || 40 || 55 || 01 || 66 || BE || 40 || 02 || AF |- | 221,5 || 0,19 || 38,0 || 25 || 6A || 54 || 72 || 40 || 4C || 00 || BF || BB || 40 || 02 || 63 |- | 224,0 || 0,13 || 12,5 || 25 || 6A || 54 || 72 || 40 || 19 || 00 || 8B || C0 || 40 || 03 || C4 |- | 220,5 || 0,02 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 1A || B9 || 40 || 04 || 52 |} Die ersten drei Spalten geben die Spannung in Volt, den Strom in Ampere sowie die Leistung in Watt an, alle weiteren die empfangenen Bytes im Hex-Format. Ziel der Tabelle ist es, Muster zu erkennen und die Bytes den Werten zuzuordnen. Dabei hilft es natürlich Messungen zu erzeugen, bei dem möglichst viele Werte konstant sind und sich nur einer verändert. Beim Strom bzw. der Leistung klappt das gut, bei der Spannung ist man ohne Trenntransformator etwas auf Netzschwankungen angewiesen. Wer es selber einmal probieren will, kann die Tabelle mit einem Klick auf die Spaltenköpfe sortieren. Sortiert man z. B. nach der Spannung sieht man relativ schnell, dass diese einen Zusammenhang mit Spalte 8 hat. Anhand der übertragenen und der abgelesenen Werte kann man nun den Zusammenhang ermitteln. In der Regel ist dieser sehr einfach zu berechnen, solange er linear ist. Mathematisch kann man die Formel <math> x=a \cdot y + b </math> in einem Gleichungssystem mit den verschiedenen Werten einsetzen, wobei x der gemessenen Spannung und y dem übertragenen Wert entspricht - was natürlich auch anders herum funktioniert. Mit ein wenig Zahlengefühl muss man keine Gleichungssysteme lösen. Nimmt man die Spannungen 222,0V 222,5V und 223V und die korrespondierenden Werte 0xBC, 0xBD und 0xBE (bzw. den dezimalen Entsprechungen 188, 189 und 190) sieht man, dass die Nachkommastelle der niederwertigsten Stelle entspricht. Teilt man durch 2, bekommt man 94; 94,5 und 95 - die Differenz zu den abgelesenen Spannungen entspricht 128. Das passt auch für alle anderen Werte. e1be79d90bfb9515e2c1670920963221681eee4b 738 736 2012-04-01T13:35:34Z Chris 2 Grundlegende Protokollbeschreibung ergänzt wikitext text/x-wiki [[Datei:EMR7370_aussen.jpg|thumb|Empfänger]] Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade. Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch. =Schaltungsanalyse= Der erste Schritt zur Analyse des Ganzen führt natürlich über den Schraubendreher. Im Inneren befindet sich eine große Leiterplatte, auf der eine kleinere Huckepack sitzt. Da an dieser eine Antenne angelötet ist, ist der Funkempfänger schnell gefunden. Der Silkscreen verrät sogar die Anschlussbelegung desselben. Nachdem bei der ersten Untersuchung die Hälfte der Beschriftung durch das Modul verdeckt war, habe ich diese nochmal weiter oben angebracht, deswegen bitte nicht wundern. Auch die Buchsen- & Stiftleiste sind nicht original, sondern von mir hinzugefügt. Da die andere Seite der Leiterplatte nicht spektakulärer ist, habe ich auf ein Foto verzichtet. Das einzig halbwegs interessante ist ein I²C-EEPROM, dessen Takt- und Datenleitung an der Stiftleiste liegt. <gallery> Datei:EMR7370_bottom.jpg|Platinenunterseite Datei:EMR7370_RXM01.jpg|Funkmodul RXM01 </gallery> Zu dem Funkmodul konnte ich im Internet nur die Bestätigung über die Existenz finden, wobei dort selbst die Angabe der Betriebsspannung unterschiedlich war. =Protokollanalyse= Da die Leiterplatte mit den Bezeichnungen SCK/SDI/SDO/NSEL schon auf SPI hindeutet wusste ich ungefähr, worauf ich mich einlasse. Mit der Stift- und Buchsenleiste zwischen Funkmodul und Hauptplatine sollte es relativ einfach sein, auf dem untersten Layer (Bitübertragungsschicht, wenn man es an dieser Stelle so nennen will) zu analysieren. Also Probes angeschlossen und gleich mal den neuen Logic Analyzer getestet. Die erste Messung zeigt die übertragenen Daten vom Einschalten des Empfängers bis zur ersten Anzeige der Messwerte. Genauer betrachtet und mit aktiviertem SPI-Analyzer sieht man auch, was übertragen wird: <gallery> EMR7370_LA1.png|Übersicht EMR7370_LA2.png|Zoom auf den ersten Block </gallery> == Initialisierung == Zur mutmaßlichen Initialisierung werden folgende Daten übertragen: <pre> 0x90D9 0xA67C 0xC080 0xC081 (500ms Pause) 0xCE85 0xCE87 0xC4AB 0xC823 0xC6C7 0xB014 0xC205 0xC080 (188ms Pause) 0xC081 (4ms Pause) 0x94D9 0xC209 (5ms Pause) 0x00 0x90D9 0xC080 (52ms Pause) 0xC081 </pre> Auch nach dem Empfang eines Datenpaketes sendet die Elektronik noch ein paar Päckchen an den Empfänger: </pre> 0xCE85 0xC080 (längere Pause) 0xC081 (3ms Pause) 0xCE85 0xCE87 </pre> Hier fällt auf, dass 0xC080 und 0xC081 oft in Kombination (siehe auch oben) und vor allem in der Nähe eines Datenempfangs auftreten. Ob dahinter ein Zusammenhang steckt?!? Da ich mich schon einmal kurzzeitig mit Funkmodule aus dem Hause HopeRF auseinandergesetzt habe und deren Produkte eine ähnliche Bezeichnung haben (z. B. RFM01), habe ich auf gut Glück auf deren Homepage nochmal vorbeigeschaut. Wie durch meine vorherige Recherche erwartet, fand ich nichts, was genauso hieß oder aussah wie mein Funkmodul, allerdings blieb ich kurz am Datenblatt des RFM01 hängen. Nachdem ich ein paar der Befehle in Hex umrechnete, stellte sich ein deutlicher Wiedererkennungswert heraus! Alle (bis auf einen) der gesendeten Datensätze ließen sich sinnvoll durch die Inhalte des Datenblatts rekonstruieren - also ein voller Erfolg. Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht. ==Datenpaket== [[Datei:EMR7370_LA3.png|thumb|Datenempfang (großer Monitor erforderlich)]] Die eigentliche Datenübertragung wird durch das Interrupt-Signal NIRQ angestoßen. Das N deutet auf "negative", also einer negativen Flanke hin, was auch der Messung entspricht. Nach dem Interrupt muss zunächst ein Nibble gelesen werden, das den Datenempfang signalisiert. Anschließend kann ein vollständiges Byte an SDO (Serial Data Out - aus Sicht de Funkmoduls) bzw. MISO (Master In Slave Out) eingelesen werden. Da die Schnittstelle bitseriell ist, ist auch die Flanke sowie die Reihenfolge der Bits wichtig. In diesem Fall wird zur steigenden Flanke von SCK (Serial Clock) gelesen, während sich die Daten zur fallenden Flanke ändern. Auch wird hier das MSB (Most Significant Bit) zuerst übertragen (was auch der üblichen Leseweise von Bits entspricht). Anzumerken ist bei dem Empfänger, dass man wissen muss, wie viele Byte empfangen werden sollen. Hier sind schon sehr viele (inklusive mir) hereingefallen. Sofern das Modul dem Verhalten derer von HopeRF entspricht, wird die Übertragung durch ein Synchronisationswort angestoßen, aber nicht signalisiert, wann die Übertragung zu Ende ist. Heißt: Der Empfänger weiß zwar, wann der Sender angefangen hat, aber nicht, wann er wieder aufhört. Das ist dann Protokollsache. Weiß man also nicht, wann das Paket zu Ende ist, wird man es im dümmsten Fall auch nie merken, da der Empfänger einfach das Rauschen auf dem Kanal auswertet. Das dient aber aller höchstens als Zufallsgenerator. Wie unten in der Tabelle zu sehen, umfassen die Pakete eine Länge von 12 Bytes. Danach muss man selber den Empfänger zum Schweigen bringen bzw. zurücksetzen. =Datenanalyse= Für die Datenanalyse erzeugte ich mir durch eine definierte Last (vulgo: Glühlampe) Werte, die ich in Excel zwischen den gesendeten und auf dem EMR angezeigten Werten abglich. Hier eine kleine Tabelle einiger Werte: {| class="wikitable sortable" |- ! U !! I !! P !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 !! 9 !! 10 !! 11 |- | 220,0 || 0,00 || 0,0 || 25 || 6A || 54 || 72 || 40 || 00 || 00 || 00 || BC || 40 || 00 || 6F |- | 222,0 || 0,05 || 0,0 || 25 || 6A || 54 || 72 || 40 || 00 || 00 || 38 || BC || 40 || 00 || 37 |- | 221,0 || 0,26 || 58,0 || 25 || 6A || 54 || 72 || 40 || 74 || 01 || 0C || BA || 40 || 00 || F0 |- | 222,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 07 || BD || 40 || 00 || F1 |- | 221,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 06 || BB || 40 || 00 || F4 |- | 221,5 || 0,17 || 39,0 || 25 || 6A || 54 || 72 || 40 || 4E || 00 || B1 || BB || 40 || 00 || 71 |- | 222,5 || 0,17 || 39,5 || 25 || 6A || 54 || 72 || 40 || 4F || 00 || B2 || BD || 40 || 01 || 6C |- | 222,5 || 0,06 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 43 || BD || 40 || 01 || 25 |- | 223,0 || 0,03 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 25 || BE || 40 || 01 || 42 |- | 222,0 || 0,03 || 2,0 || 25 || 6A || 54 || 72 || 40 || 04 || 00 || 20 || BC || 40 || 01 || 4A |- | 222,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3E || BD || 40 || 01 || 2D |- | 223,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3C || BF || 40 || 01 || 2D |- | 222,5 || 0,31 || 29,0 || 25 || 6A || 54 || 72 || 40 || 3A || 01 || 3E || BD || 40 || 01 || F4 |- | 222,0 || 0,37 || 42,0 || 25 || 6A || 54 || 72 || 40 || 54 || 01 || 74 || BC || 40 || 01 || A5 |- | 223,0 || 0,35 || 42,5 || 25 || 6A || 54 || 72 || 40 || 55 || 01 || 66 || BE || 40 || 02 || AF |- | 221,5 || 0,19 || 38,0 || 25 || 6A || 54 || 72 || 40 || 4C || 00 || BF || BB || 40 || 02 || 63 |- | 224,0 || 0,13 || 12,5 || 25 || 6A || 54 || 72 || 40 || 19 || 00 || 8B || C0 || 40 || 03 || C4 |} Die ersten drei Spalten geben die Spannung in Volt, den Strom in Ampere sowie die Leistung in Watt an, alle weiteren die empfangenen Bytes im Hex-Format. Ziel der Tabelle ist es, Muster zu erkennen und die Bytes den Werten zuzuordnen. Dabei hilft es natürlich Messungen zu erzeugen, bei dem möglichst viele Werte konstant sind und sich nur einer verändert. Beim Strom bzw. der Leistung klappt das gut, bei der Spannung ist man ohne Trenntransformator etwas auf Netzschwankungen angewiesen. Wer es selber einmal probieren will, kann die Tabelle mit einem Klick auf die Spaltenköpfe sortieren. ==Spannung== Sortiert man z. B. nach der Spannung sieht man relativ schnell, dass diese einen Zusammenhang mit Spalte 8 hat. Anhand der übertragenen und der abgelesenen Werte kann man nun den Zusammenhang ermitteln. In der Regel ist dieser sehr einfach zu berechnen, solange er linear ist. Mathematisch kann man die Formel <math> x=a \cdot y + b </math> in einem Gleichungssystem mit den verschiedenen Werten einsetzen, wobei x der gemessenen Spannung und y dem übertragenen Wert entspricht - was natürlich auch anders herum funktioniert. Mit ein wenig Zahlengefühl muss man keine Gleichungssysteme lösen. Nimmt man die Spannungen 222,0V 222,5V und 223V und die korrespondierenden Werte 0xBC, 0xBD und 0xBE (bzw. den dezimalen Entsprechungen 188, 189 und 190) sieht man, dass die Nachkommastelle der niederwertigsten Stelle entspricht. Teilt man durch 2, bekommt man 94; 94,5 und 95 - die Differenz zu den abgelesenen Spannungen entspricht 128. Das passt auch für alle anderen Werte. ==Leistung== Die Unterscheidung zwischen Strom und Leistung ist schon etwas schwieriger. Zu meinem Glück (und warum auch immer) habe ich bei einem Messwert eine Leistung von 0W und gleichzeitig einen Strom > 0A erfasst. Sucht man zugleich die Spalten mit zur Leistung korrespondierenden Werten heraus, kommt man auf Spalte 4 und 5, wobei in Spalte 4 das 7. Bit ignoriert werden muss. Ein Gleichungssystem muss man auch hier nicht ansetzen, da die angezeigte Leistung sich nur in 0,5-Schritten ändert, ist wie bei der Spannung anzunehmen, dass man den empfangenen Wert nur durch 2 teilen muss. ==Strom== Ab hier ist nun langsam eine Auswahl durch Ausschlussverfahren möglich. Die Werte zwischen Leistung und Spannung in (Spalte 6 und 7) umgewandelt und siehe da - der Strom in mA. Bei genauerem Hinsehen fällt auf, dass der angezeigte Strom im Empfänger nicht richtig gerundet, sondern nur abgeschnitten wird. ==Adresse== Die Adresse findet man am leichtesten heraus, wenn man beide Sender gleichzeitig betreibt. Was in der Tabelle oben nicht zu sehen ist, zeigt sich mit dem Logic Analyzer sehr schnell - Spalte 2 und 3 dienen der Adressierung. ==Geräteklasse (?)== Die ersten beiden Bytes haben sich bei keinen der empfangenen Pakete unterschieden, daher gehe ich davon aus, dass es sich dabei lediglich um eine Identifikation der Geräteklasse handelt oder zumindest um eine Synchronisation auf höherer Ebene handelt. ==Energie== Auffällig am Empfänger ist, dass dieser auch nach einem Reset über die genutzte Energie der letzten Tage Bescheid "wusste". Das ist entweder durch schwarze Magie oder durch ein weiteres Byte im Datenpaket zu erklären. Da letzteres deutlich plausibler ist und noch zwei Spalten nicht identifiziert sind, lasse ich die Glaskugel in der Schublade. (noch nicht 100% sicher) ==Prüfsumme== Da es sich um eine Funkübertragung handelt, ist eine Prüfsumme Pflicht. Um speichersparend zu arbeiten, wird diese in der Regel on-the-fly berechnetund am Ende gesendet. Mit dem CRC8-Code des [[VBus-Decoder]]s hatte ich auf Anhieb erfolg. b9d3cfa9fecc7ca127aac56fd442bf797b79d470 740 738 2012-04-01T15:13:08Z Chris 2 Download wikitext text/x-wiki [[Datei:EMR7370_aussen.jpg|thumb|Empfänger]] Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade. Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch. =Schaltungsanalyse= Der erste Schritt zur Analyse des Ganzen führt natürlich über den Schraubendreher. Im Inneren befindet sich eine große Leiterplatte, auf der eine kleinere Huckepack sitzt. Da an dieser eine Antenne angelötet ist, ist der Funkempfänger schnell gefunden. Der Silkscreen verrät sogar die Anschlussbelegung desselben. Nachdem bei der ersten Untersuchung die Hälfte der Beschriftung durch das Modul verdeckt war, habe ich diese nochmal weiter oben angebracht, deswegen bitte nicht wundern. Auch die Buchsen- & Stiftleiste sind nicht original, sondern von mir hinzugefügt. Da die andere Seite der Leiterplatte nicht spektakulärer ist, habe ich auf ein Foto verzichtet. Das einzig halbwegs interessante ist ein I²C-EEPROM, dessen Takt- und Datenleitung an der Stiftleiste liegt. <gallery> Datei:EMR7370_bottom.jpg|Platinenunterseite Datei:EMR7370_RXM01.jpg|Funkmodul RXM01 </gallery> Zu dem Funkmodul konnte ich im Internet nur die Bestätigung über die Existenz finden, wobei dort selbst die Angabe der Betriebsspannung unterschiedlich war. =Protokollanalyse= Da die Leiterplatte mit den Bezeichnungen SCK/SDI/SDO/NSEL schon auf SPI hindeutet wusste ich ungefähr, worauf ich mich einlasse. Mit der Stift- und Buchsenleiste zwischen Funkmodul und Hauptplatine sollte es relativ einfach sein, auf dem untersten Layer (Bitübertragungsschicht, wenn man es an dieser Stelle so nennen will) zu analysieren. Also Probes angeschlossen und gleich mal den neuen Logic Analyzer getestet. Die erste Messung zeigt die übertragenen Daten vom Einschalten des Empfängers bis zur ersten Anzeige der Messwerte. Genauer betrachtet und mit aktiviertem SPI-Analyzer sieht man auch, was übertragen wird: <gallery> EMR7370_LA1.png|Übersicht EMR7370_LA2.png|Zoom auf den ersten Block </gallery> == Initialisierung == Zur mutmaßlichen Initialisierung werden folgende Daten übertragen: <pre> 0x90D9 0xA67C 0xC080 0xC081 (500ms Pause) 0xCE85 0xCE87 0xC4AB 0xC823 0xC6C7 0xB014 0xC205 0xC080 (188ms Pause) 0xC081 (4ms Pause) 0x94D9 0xC209 (5ms Pause) 0x00 0x90D9 0xC080 (52ms Pause) 0xC081 </pre> Auch nach dem Empfang eines Datenpaketes sendet die Elektronik noch ein paar Päckchen an den Empfänger: </pre> 0xCE85 0xC080 (längere Pause) 0xC081 (3ms Pause) 0xCE85 0xCE87 </pre> Hier fällt auf, dass 0xC080 und 0xC081 oft in Kombination (siehe auch oben) und vor allem in der Nähe eines Datenempfangs auftreten. Ob dahinter ein Zusammenhang steckt?!? Da ich mich schon einmal kurzzeitig mit Funkmodule aus dem Hause HopeRF auseinandergesetzt habe und deren Produkte eine ähnliche Bezeichnung haben (z. B. RFM01), habe ich auf gut Glück auf deren Homepage nochmal vorbeigeschaut. Wie durch meine vorherige Recherche erwartet, fand ich nichts, was genauso hieß oder aussah wie mein Funkmodul, allerdings blieb ich kurz am Datenblatt des RFM01 hängen. Nachdem ich ein paar der Befehle in Hex umrechnete, stellte sich ein deutlicher Wiedererkennungswert heraus! Alle (bis auf einen) der gesendeten Datensätze ließen sich sinnvoll durch die Inhalte des Datenblatts rekonstruieren - also ein voller Erfolg. Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht. ==Datenpaket== [[Datei:EMR7370_LA3.png|thumb|Datenempfang (großer Monitor erforderlich)]] Die eigentliche Datenübertragung wird durch das Interrupt-Signal NIRQ angestoßen. Das N deutet auf "negative", also einer negativen Flanke hin, was auch der Messung entspricht. Nach dem Interrupt muss zunächst ein Nibble gelesen werden, das den Datenempfang signalisiert. Anschließend kann ein vollständiges Byte an SDO (Serial Data Out - aus Sicht de Funkmoduls) bzw. MISO (Master In Slave Out) eingelesen werden. Da die Schnittstelle bitseriell ist, ist auch die Flanke sowie die Reihenfolge der Bits wichtig. In diesem Fall wird zur steigenden Flanke von SCK (Serial Clock) gelesen, während sich die Daten zur fallenden Flanke ändern. Auch wird hier das MSB (Most Significant Bit) zuerst übertragen (was auch der üblichen Leseweise von Bits entspricht). Anzumerken ist bei dem Empfänger, dass man wissen muss, wie viele Byte empfangen werden sollen. Hier sind schon sehr viele (inklusive mir) hereingefallen. Sofern das Modul dem Verhalten derer von HopeRF entspricht, wird die Übertragung durch ein Synchronisationswort angestoßen, aber nicht signalisiert, wann die Übertragung zu Ende ist. Heißt: Der Empfänger weiß zwar, wann der Sender angefangen hat, aber nicht, wann er wieder aufhört. Das ist dann Protokollsache. Weiß man also nicht, wann das Paket zu Ende ist, wird man es im dümmsten Fall auch nie merken, da der Empfänger einfach das Rauschen auf dem Kanal auswertet. Das dient aber aller höchstens als Zufallsgenerator. Wie unten in der Tabelle zu sehen, umfassen die Pakete eine Länge von 12 Bytes. Danach muss man selber den Empfänger zum Schweigen bringen bzw. zurücksetzen. ==Anmeldung== Zur Anmeldung eines Senders am Empfänger muss die Verbindungs-Taste länger gedrückt werden, danach wird immer wieder 0x25 0x2A, die Adresse (2 Byte) sowie (vermutlich) eine Prüfsumme gesendet. Da die Anmeldung zum Betreiben eines eigenen Empfängers nicht erforderlich ist, behandle ich diese nicht weiter. =Datenanalyse= Für die Datenanalyse erzeugte ich mir durch eine definierte Last (vulgo: Glühlampe) Werte, die ich in Excel zwischen den gesendeten und auf dem EMR angezeigten Werten abglich. Hier eine kleine Tabelle einiger Werte: {| class="wikitable sortable" |- ! U !! I !! P !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 !! 9 !! 10 !! 11 |- | 220,0 || 0,00 || 0,0 || 25 || 6A || 54 || 72 || 40 || 00 || 00 || 00 || BC || 40 || 00 || 6F |- | 222,0 || 0,05 || 0,0 || 25 || 6A || 54 || 72 || 40 || 00 || 00 || 38 || BC || 40 || 00 || 37 |- | 221,0 || 0,26 || 58,0 || 25 || 6A || 54 || 72 || 40 || 74 || 01 || 0C || BA || 40 || 00 || F0 |- | 222,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 07 || BD || 40 || 00 || F1 |- | 221,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 06 || BB || 40 || 00 || F4 |- | 221,5 || 0,17 || 39,0 || 25 || 6A || 54 || 72 || 40 || 4E || 00 || B1 || BB || 40 || 00 || 71 |- | 222,5 || 0,17 || 39,5 || 25 || 6A || 54 || 72 || 40 || 4F || 00 || B2 || BD || 40 || 01 || 6C |- | 222,5 || 0,06 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 43 || BD || 40 || 01 || 25 |- | 223,0 || 0,03 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 25 || BE || 40 || 01 || 42 |- | 222,0 || 0,03 || 2,0 || 25 || 6A || 54 || 72 || 40 || 04 || 00 || 20 || BC || 40 || 01 || 4A |- | 222,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3E || BD || 40 || 01 || 2D |- | 223,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3C || BF || 40 || 01 || 2D |- | 222,5 || 0,31 || 29,0 || 25 || 6A || 54 || 72 || 40 || 3A || 01 || 3E || BD || 40 || 01 || F4 |- | 222,0 || 0,37 || 42,0 || 25 || 6A || 54 || 72 || 40 || 54 || 01 || 74 || BC || 40 || 01 || A5 |- | 223,0 || 0,35 || 42,5 || 25 || 6A || 54 || 72 || 40 || 55 || 01 || 66 || BE || 40 || 02 || AF |- | 221,5 || 0,19 || 38,0 || 25 || 6A || 54 || 72 || 40 || 4C || 00 || BF || BB || 40 || 02 || 63 |- | 224,0 || 0,13 || 12,5 || 25 || 6A || 54 || 72 || 40 || 19 || 00 || 8B || C0 || 40 || 03 || C4 |} Die ersten drei Spalten geben die Spannung in Volt, den Strom in Ampere sowie die Leistung in Watt an, alle weiteren die empfangenen Bytes im Hex-Format. Ziel der Tabelle ist es, Muster zu erkennen und die Bytes den Werten zuzuordnen. Dabei hilft es natürlich Messungen zu erzeugen, bei dem möglichst viele Werte konstant sind und sich nur einer verändert. Beim Strom bzw. der Leistung klappt das gut, bei der Spannung ist man ohne Trenntransformator etwas auf Netzschwankungen angewiesen. Wer es selber einmal probieren will, kann die Tabelle mit einem Klick auf die Spaltenköpfe sortieren. ==Spannung== Sortiert man z. B. nach der Spannung sieht man relativ schnell, dass diese einen Zusammenhang mit Spalte 8 hat. Anhand der übertragenen und der abgelesenen Werte kann man nun den Zusammenhang ermitteln. In der Regel ist dieser sehr einfach zu berechnen, solange er linear ist. Mathematisch kann man die Formel <math> x=a \cdot y + b </math> in einem Gleichungssystem mit den verschiedenen Werten einsetzen, wobei x der gemessenen Spannung und y dem übertragenen Wert entspricht - was natürlich auch anders herum funktioniert. Mit ein wenig Zahlengefühl muss man keine Gleichungssysteme lösen. Nimmt man die Spannungen 222,0V 222,5V und 223V und die korrespondierenden Werte 0xBC, 0xBD und 0xBE (bzw. den dezimalen Entsprechungen 188, 189 und 190) sieht man, dass die Nachkommastelle der niederwertigsten Stelle entspricht. Teilt man durch 2, bekommt man 94; 94,5 und 95 - die Differenz zu den abgelesenen Spannungen entspricht 128. Das passt auch für alle anderen Werte. ==Leistung== Die Unterscheidung zwischen Strom und Leistung ist schon etwas schwieriger. Zu meinem Glück (und warum auch immer) habe ich bei einem Messwert eine Leistung von 0W und gleichzeitig einen Strom > 0A erfasst. Sucht man zugleich die Spalten mit zur Leistung korrespondierenden Werten heraus, kommt man auf Spalte 4 und 5, wobei in Spalte 4 das 7. Bit ignoriert werden muss. Ein Gleichungssystem muss man auch hier nicht ansetzen, da die angezeigte Leistung sich nur in 0,5-Schritten ändert, ist wie bei der Spannung anzunehmen, dass man den empfangenen Wert nur durch 2 teilen muss. ==Strom== Ab hier ist nun langsam eine Auswahl durch Ausschlussverfahren möglich. Die Werte zwischen Leistung und Spannung in (Spalte 6 und 7) umgewandelt und siehe da - der Strom in mA. Bei genauerem Hinsehen fällt auf, dass der angezeigte Strom im Empfänger nicht richtig gerundet, sondern nur abgeschnitten wird. ==Adresse== Die Adresse findet man am leichtesten heraus, wenn man beide Sender gleichzeitig betreibt. Was in der Tabelle oben nicht zu sehen ist, zeigt sich mit dem Logic Analyzer sehr schnell - Spalte 2 und 3 dienen der Adressierung. ==Geräteklasse (?)== Die ersten beiden Bytes haben sich bei keinen der empfangenen Pakete (außer bei der Anmeldung) unterschieden, daher gehe ich davon aus, dass es sich dabei lediglich um eine Identifikation der Geräteklasse handelt oder zumindest um eine Synchronisation auf höherer Ebene handelt. ==Energie== Auffällig am Empfänger ist, dass dieser auch nach einem Reset über die genutzte Energie der letzten Tage Bescheid "wusste". Die zugehörigen Werte stehen in Spalte 9 und 10, wobei auch hier wieder ein Offset von 0x4000 bzw. 16384 zu verzeichnen ist. Die Skalierung ist hierbei etwas krumm, geteilt durch 100 ergibt sich die Energie in kWh, somit wird intern in 10Wh-Schritten gezählt. ==Prüfsumme== Da es sich um eine Funkübertragung handelt, ist eine Prüfsumme Pflicht. Um speichersparend zu arbeiten, wird diese in der Regel on-the-fly berechnetund am Ende gesendet. Mit dem CRC8-Code des [[VBus-Decoder]]s hatte ich auf Anhieb Erfolg. ==Zusammenfassung== {| class="wikitable" |- ! Wert !! MSByte !! LSByte !! Offset !! Faktor !! Bemerkung |- | Klasse || 0 || 1 || -- || -- || keine anderen Werte bekannt |- | Adresse || 2 || 3 || -- || -- || |- | Leistung || 4 || 5 || 0x4000 || 0,5 || W |- | Strom || 6 || 7 || 0x0000|| 0,001 || A |- | Spannung || 8 || -- || 0x0000 || 0,5 || V |- | Energie || 9 || 10 || 0x4000 || 0,01 || kWh |- | Prüfsumme || 11 || -- || -- || -- || CRC aller vorangegangenen Bytes |} =Client= Der nächste Schritt ist natürlich einen eigenen Client zu programmieren. =Download= * [[Datei:EMR7370.zip]] LA-Aufzeichnungen (mit [http://www.saleae.com/downloads Saleae Logic] einsehbar), Excel-Datei mit ausgewerteten Beispieldatensätzen 9a83ccb77b903ccae8529f6c860d3862b4066225 743 740 2012-04-28T21:10:22Z Chris 2 Quellcode ergänzt wikitext text/x-wiki [[Datei:EMR7370_aussen.jpg|thumb|Empfänger]] Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade. Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch. =Schaltungsanalyse= Der erste Schritt zur Analyse des Ganzen führt natürlich über den Schraubendreher. Im Inneren befindet sich eine große Leiterplatte, auf der eine kleinere Huckepack sitzt. Da an dieser eine Antenne angelötet ist, ist der Funkempfänger schnell gefunden. Der Silkscreen verrät sogar die Anschlussbelegung desselben. Nachdem bei der ersten Untersuchung die Hälfte der Beschriftung durch das Modul verdeckt war, habe ich diese nochmal weiter oben angebracht, deswegen bitte nicht wundern. Auch die Buchsen- & Stiftleiste sind nicht original, sondern von mir hinzugefügt. Da die andere Seite der Leiterplatte nicht spektakulärer ist, habe ich auf ein Foto verzichtet. Das einzig halbwegs interessante ist ein I²C-EEPROM, dessen Takt- und Datenleitung an der Stiftleiste liegt. <gallery> Datei:EMR7370_bottom.jpg|Platinenunterseite Datei:EMR7370_RXM01.jpg|Funkmodul RXM01 </gallery> Zu dem Funkmodul konnte ich im Internet nur die Bestätigung über die Existenz finden, wobei dort selbst die Angabe der Betriebsspannung unterschiedlich war. =Protokollanalyse= Da die Leiterplatte mit den Bezeichnungen SCK/SDI/SDO/NSEL schon auf SPI hindeutet wusste ich ungefähr, worauf ich mich einlasse. Mit der Stift- und Buchsenleiste zwischen Funkmodul und Hauptplatine sollte es relativ einfach sein, auf dem untersten Layer (Bitübertragungsschicht, wenn man es an dieser Stelle so nennen will) zu analysieren. Also Probes angeschlossen und gleich mal den neuen Logic Analyzer getestet. Die erste Messung zeigt die übertragenen Daten vom Einschalten des Empfängers bis zur ersten Anzeige der Messwerte. Genauer betrachtet und mit aktiviertem SPI-Analyzer sieht man auch, was übertragen wird: <gallery> EMR7370_LA1.png|Übersicht EMR7370_LA2.png|Zoom auf den ersten Block </gallery> == Initialisierung == Zur mutmaßlichen Initialisierung werden folgende Daten übertragen: <pre> 0x90D9 0xA67C 0xC080 0xC081 (500ms Pause) 0xCE85 0xCE87 0xC4AB 0xC823 0xC6C7 0xB014 0xC205 0xC080 (188ms Pause) 0xC081 (4ms Pause) 0x94D9 0xC209 (5ms Pause) 0x00 0x90D9 0xC080 (52ms Pause) 0xC081 </pre> Auch nach dem Empfang eines Datenpaketes sendet die Elektronik noch ein paar Päckchen an den Empfänger: </pre> 0xCE85 0xC080 (längere Pause) 0xC081 (3ms Pause) 0xCE85 0xCE87 </pre> Hier fällt auf, dass 0xC080 und 0xC081 oft in Kombination (siehe auch oben) und vor allem in der Nähe eines Datenempfangs auftreten. Ob dahinter ein Zusammenhang steckt?!? Da ich mich schon einmal kurzzeitig mit Funkmodule aus dem Hause HopeRF auseinandergesetzt habe und deren Produkte eine ähnliche Bezeichnung haben (z. B. RFM01), habe ich auf gut Glück auf deren Homepage nochmal vorbeigeschaut. Wie durch meine vorherige Recherche erwartet, fand ich nichts, was genauso hieß oder aussah wie mein Funkmodul, allerdings blieb ich kurz am Datenblatt des RFM01 hängen. Nachdem ich ein paar der Befehle in Hex umrechnete, stellte sich ein deutlicher Wiedererkennungswert heraus! Alle (bis auf einen) der gesendeten Datensätze ließen sich sinnvoll durch die Inhalte des Datenblatts rekonstruieren - also ein voller Erfolg. Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht. ==Datenpaket== [[Datei:EMR7370_LA3.png|thumb|Datenempfang (großer Monitor erforderlich)]] Die eigentliche Datenübertragung wird durch das Interrupt-Signal NIRQ angestoßen. Das N deutet auf "negative", also einer negativen Flanke hin, was auch der Messung entspricht. Nach dem Interrupt muss zunächst ein Nibble gelesen werden, das den Datenempfang signalisiert. Anschließend kann ein vollständiges Byte an SDO (Serial Data Out - aus Sicht de Funkmoduls) bzw. MISO (Master In Slave Out) eingelesen werden. Da die Schnittstelle bitseriell ist, ist auch die Flanke sowie die Reihenfolge der Bits wichtig. In diesem Fall wird zur steigenden Flanke von SCK (Serial Clock) gelesen, während sich die Daten zur fallenden Flanke ändern. Auch wird hier das MSB (Most Significant Bit) zuerst übertragen (was auch der üblichen Leseweise von Bits entspricht). Anzumerken ist bei dem Empfänger, dass man wissen muss, wie viele Byte empfangen werden sollen. Hier sind schon sehr viele (inklusive mir) hereingefallen. Sofern das Modul dem Verhalten derer von HopeRF entspricht, wird die Übertragung durch ein Synchronisationswort angestoßen, aber nicht signalisiert, wann die Übertragung zu Ende ist. Heißt: Der Empfänger weiß zwar, wann der Sender angefangen hat, aber nicht, wann er wieder aufhört. Das ist dann Protokollsache. Weiß man also nicht, wann das Paket zu Ende ist, wird man es im dümmsten Fall auch nie merken, da der Empfänger einfach das Rauschen auf dem Kanal auswertet. Das dient aber aller höchstens als Zufallsgenerator. Wie unten in der Tabelle zu sehen, umfassen die Pakete eine Länge von 12 Bytes. Danach muss man selber den Empfänger zum Schweigen bringen bzw. zurücksetzen. ==Anmeldung== Zur Anmeldung eines Senders am Empfänger muss die Verbindungs-Taste länger gedrückt werden, danach wird immer wieder 0x25 0x2A, die Adresse (2 Byte) sowie (vermutlich) eine Prüfsumme gesendet. Da die Anmeldung zum Betreiben eines eigenen Empfängers nicht erforderlich ist, behandle ich diese nicht weiter. =Datenanalyse= Für die Datenanalyse erzeugte ich mir durch eine definierte Last (vulgo: Glühlampe) Werte, die ich in Excel zwischen den gesendeten und auf dem EMR angezeigten Werten abglich. Hier eine kleine Tabelle einiger Werte: {| class="wikitable sortable" |- ! U !! I !! P !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 !! 9 !! 10 !! 11 |- | 220,0 || 0,00 || 0,0 || 25 || 6A || 54 || 72 || 40 || 00 || 00 || 00 || BC || 40 || 00 || 6F |- | 222,0 || 0,05 || 0,0 || 25 || 6A || 54 || 72 || 40 || 00 || 00 || 38 || BC || 40 || 00 || 37 |- | 221,0 || 0,26 || 58,0 || 25 || 6A || 54 || 72 || 40 || 74 || 01 || 0C || BA || 40 || 00 || F0 |- | 222,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 07 || BD || 40 || 00 || F1 |- | 221,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 06 || BB || 40 || 00 || F4 |- | 221,5 || 0,17 || 39,0 || 25 || 6A || 54 || 72 || 40 || 4E || 00 || B1 || BB || 40 || 00 || 71 |- | 222,5 || 0,17 || 39,5 || 25 || 6A || 54 || 72 || 40 || 4F || 00 || B2 || BD || 40 || 01 || 6C |- | 222,5 || 0,06 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 43 || BD || 40 || 01 || 25 |- | 223,0 || 0,03 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 25 || BE || 40 || 01 || 42 |- | 222,0 || 0,03 || 2,0 || 25 || 6A || 54 || 72 || 40 || 04 || 00 || 20 || BC || 40 || 01 || 4A |- | 222,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3E || BD || 40 || 01 || 2D |- | 223,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3C || BF || 40 || 01 || 2D |- | 222,5 || 0,31 || 29,0 || 25 || 6A || 54 || 72 || 40 || 3A || 01 || 3E || BD || 40 || 01 || F4 |- | 222,0 || 0,37 || 42,0 || 25 || 6A || 54 || 72 || 40 || 54 || 01 || 74 || BC || 40 || 01 || A5 |- | 223,0 || 0,35 || 42,5 || 25 || 6A || 54 || 72 || 40 || 55 || 01 || 66 || BE || 40 || 02 || AF |- | 221,5 || 0,19 || 38,0 || 25 || 6A || 54 || 72 || 40 || 4C || 00 || BF || BB || 40 || 02 || 63 |- | 224,0 || 0,13 || 12,5 || 25 || 6A || 54 || 72 || 40 || 19 || 00 || 8B || C0 || 40 || 03 || C4 |} Die ersten drei Spalten geben die Spannung in Volt, den Strom in Ampere sowie die Leistung in Watt an, alle weiteren die empfangenen Bytes im Hex-Format. Ziel der Tabelle ist es, Muster zu erkennen und die Bytes den Werten zuzuordnen. Dabei hilft es natürlich Messungen zu erzeugen, bei dem möglichst viele Werte konstant sind und sich nur einer verändert. Beim Strom bzw. der Leistung klappt das gut, bei der Spannung ist man ohne Trenntransformator etwas auf Netzschwankungen angewiesen. Wer es selber einmal probieren will, kann die Tabelle mit einem Klick auf die Spaltenköpfe sortieren. ==Spannung== Sortiert man z. B. nach der Spannung sieht man relativ schnell, dass diese einen Zusammenhang mit Spalte 8 hat. Anhand der übertragenen und der abgelesenen Werte kann man nun den Zusammenhang ermitteln. In der Regel ist dieser sehr einfach zu berechnen, solange er linear ist. Mathematisch kann man die Formel <math> x=a \cdot y + b </math> in einem Gleichungssystem mit den verschiedenen Werten einsetzen, wobei x der gemessenen Spannung und y dem übertragenen Wert entspricht - was natürlich auch anders herum funktioniert. Mit ein wenig Zahlengefühl muss man keine Gleichungssysteme lösen. Nimmt man die Spannungen 222,0V 222,5V und 223V und die korrespondierenden Werte 0xBC, 0xBD und 0xBE (bzw. den dezimalen Entsprechungen 188, 189 und 190) sieht man, dass die Nachkommastelle der niederwertigsten Stelle entspricht. Teilt man durch 2, bekommt man 94; 94,5 und 95 - die Differenz zu den abgelesenen Spannungen entspricht 128. Das passt auch für alle anderen Werte. ==Leistung== Die Unterscheidung zwischen Strom und Leistung ist schon etwas schwieriger. Zu meinem Glück (und warum auch immer) habe ich bei einem Messwert eine Leistung von 0W und gleichzeitig einen Strom > 0A erfasst. Sucht man zugleich die Spalten mit zur Leistung korrespondierenden Werten heraus, kommt man auf Spalte 4 und 5, wobei in Spalte 4 das 7. Bit ignoriert werden muss. Ein Gleichungssystem muss man auch hier nicht ansetzen, da die angezeigte Leistung sich nur in 0,5-Schritten ändert, ist wie bei der Spannung anzunehmen, dass man den empfangenen Wert nur durch 2 teilen muss. ==Strom== Ab hier ist nun langsam eine Auswahl durch Ausschlussverfahren möglich. Die Werte zwischen Leistung und Spannung in (Spalte 6 und 7) umgewandelt und siehe da - der Strom in mA. Bei genauerem Hinsehen fällt auf, dass der angezeigte Strom im Empfänger nicht richtig gerundet, sondern nur abgeschnitten wird. ==Adresse== Die Adresse findet man am leichtesten heraus, wenn man beide Sender gleichzeitig betreibt. Was in der Tabelle oben nicht zu sehen ist, zeigt sich mit dem Logic Analyzer sehr schnell - Spalte 2 und 3 dienen der Adressierung. ==Geräteklasse (?)== Die ersten beiden Bytes haben sich bei keinen der empfangenen Pakete (außer bei der Anmeldung) unterschieden, daher gehe ich davon aus, dass es sich dabei lediglich um eine Identifikation der Geräteklasse handelt oder zumindest um eine Synchronisation auf höherer Ebene handelt. ==Energie== Auffällig am Empfänger ist, dass dieser auch nach einem Reset über die genutzte Energie der letzten Tage Bescheid "wusste". Die zugehörigen Werte stehen in Spalte 9 und 10, wobei auch hier wieder ein Offset von 0x4000 bzw. 16384 zu verzeichnen ist. Die Skalierung ist hierbei etwas krumm, geteilt durch 100 ergibt sich die Energie in kWh, somit wird intern in 10Wh-Schritten gezählt. ==Prüfsumme== Da es sich um eine Funkübertragung handelt, ist eine Prüfsumme Pflicht. Um speichersparend zu arbeiten, wird diese in der Regel on-the-fly berechnetund am Ende gesendet. Mit dem CRC8-Code des [[VBus-Decoder]]s hatte ich auf Anhieb Erfolg. ==Zusammenfassung== {| class="wikitable" |- ! Wert !! MSByte !! LSByte !! Offset !! Faktor !! Bemerkung |- | Klasse || 0 || 1 || -- || -- || keine anderen Werte bekannt |- | Adresse || 2 || 3 || -- || -- || |- | Leistung || 4 || 5 || 0x4000 || 0,5 || W |- | Strom || 6 || 7 || 0x0000|| 0,001 || A |- | Spannung || 8 || -- || 0x0000 || 0,5 || V |- | Energie || 9 || 10 || 0x4000 || 0,01 || kWh |- | Prüfsumme || 11 || -- || -- || -- || CRC aller vorangegangenen Bytes |} =Client= {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = D1 | FuseL = F8 }} Der nächste Schritt ist natürlich einen eigenen Client zu programmieren. Verwendet habe ich hierzu den mittlerweile doch etwas betagten ATmega8, der jedoch nach wie vor seinen Zweck erfüllt. Um es einfach zu halten habe ich das SPI-Interface im Bitbanging-Mode geschrieben, wobei auch die benötigten Pausen (vom Original übernommen) womöglich etwas vorsichtig gewählt sind. Ich halte jedoch niemanden ab, das Timing zu optimieren. Die Software führt zunächst eine Initialisierung der Hardware durch und überprüft dann im Main-Loop, ob ein vollständiges Datenpaket empfangen wurde. Ist dies der Fall, wird das Paket dekodiert und bei Erfolg in an den entsprechenden Speicherplatz geschoben. Ohne höheren Debug-Level muss man die Adressen der jeweiligen Sender vorher setzen, sonst sieht man nichts. Standardmäßig werden die Messdaten alle 10 Sekunden ausgegeben, wird 30 Sekunden nichts empfangen, wird der Empfänger neu initialisiert, wobei ich damit noch etwas unzufrieden bin: Während Flashen des AVRs ist es immer wieder passiert, dass der Empfänger den Interrupt gesetzt hat, dieser aber nicht abgearbeitet wurde. Das hat zur Folge, dass der Empfang auch nach erneutem Initialisieren einfach nicht funktioniert. Da das Funkmodul keinen Reset-Eingang hat, hilft hier entweder eine bessere Behandlung des Interrupts oder die die Versorgung des Empfängers über den Mikrocontroller zu schalten. Letzteres ist zwar nicht elegant, dafür aber effektiv. Eine der beiden Methoden müsste zur Erhöhung der Zuverlässigkeit noch implementiert werden. Die Pinbelegung des Funkmoduls ist der Datei RFM01.h zu entnehmen. Die Ausgabe der Daten erfolgt am UART mit 57600 Baud 8N1. =Download= * [[Datei:EMR7370.zip]] LA-Aufzeichnungen (mit [http://www.saleae.com/downloads Saleae Logic] einsehbar), Excel-Datei mit ausgewerteten Beispieldatensätzen, Beispielcode ATmega8 (AVR-Studio 5) 004664f4c857d48f104d55204de19d6904c8c0fc Datei:EMR7370 LA3.png 6 294 733 2012-03-15T21:40:12Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Benutzer:Chris 2 45 737 709 2012-03-16T18:42:30Z Chris 2 wikitext text/x-wiki = Wie es dazu kam = Irgendwann um 2003 fing ich damit an, meine (mehr oder weniger gelungenen) Bastel-Projekte in HTML zu verwandeln und auf hobby-elektronik.de.vu zu veröffentlichen. Der Speicherplatz bei Tripod wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich irgendwann, auf das schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10 April 2005 die Domain hobbyelektronik.org registriert. Zu .org kam es, da mir eine Woche davor jemand die .net-Domain weggeschnappte. Im Nachhinein bin ich glücklich, dem damaligen .net-Hype entgangen zu sein. Eine richtige Organisation sind wir zwar noch immer nicht aber was nicht ist, kann ja noch werden ;) = Was ich mache = Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" bezeichnen. Seit Oktober 2009 studiere ich Elektrotechnik/Nachrichtentechnik an der [http://www.hs-ulm.de Hochschule Ulm]. Die Schnittmenge bzw. vielmehr die Kombination aus den beiden Bereichen kommen auch wieder in meinen Hobbys zusammen. = Warum das Ganze? = Ganz einfach: Weil es mir Spaß macht. Wie an anderer Stelle schon erwähnt, bezeichne ich diese Seite als "nicht-kommerzielles Umfeld". Damit ist gemeint, dass ich mit dieser Homepage kein Geld verdiene (keine Werbung, keine Partnerschaften mir irgendwelchen Firmen, etc.) und es ehrlich gesagt auch nicht will. Das bedeutet auch, dass Produkterwähnungen und evtl. auch Empfehlungen aus meiner eigenen Erfahrung und Meinung gemacht werden. (Wer spenden will - gerne auch Sachspenden - ist natürlich willkommen ;)). Neben dem Spaß geht es mir auch darum, etwas an andere Bastler, Elektronik-Einsteiger und DICH weiter- bzw. zurückzugeben. Auch ich habe mal sehr klein angefangen und war froh um alles, was mich näher in Richtung Computer und Elektronik brachte (und auch heute noch bringt). Wenn man so will, kann man es als Kreislauf verstehen :) [http://sprut.de/misc/hpphilos.htm Sprut] hat es meiner Meinung mit seiner Homepage-Philosophie sehr gut getroffen. = Kannst du mir... = ...bei <Thema hier einsetzen> helfen? Jein. Wenn du ehrliches Interesse hast, helfe ich gerne. Was ich allerdings überhaupt nicht abkann ist die "Mach mal-" bzw. "Freibiermentalität", die manche an den Tag legen. Solche können erst wiederkommen, wenn ich einen Gewerbeschein habe... = Kontakt = Solltest du Fragen, Kritik, Verbesserungsvorschläge oder Fehler auf den Seiten hier gefunden haben - eine kleine Mail genügt und wird gerne beantwortet: chris at hobbyelektronik punkt org (siehe auch [[Hobbyelektronik.org:Impressum|Impressum]]) b33cd2648387436c2fc3352b12d9bf5376a688e4 Datei:EMR7370.zip 6 295 739 2012-04-01T15:10:45Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 741 739 2012-04-28T20:52:40Z Chris 2 lud eine neue Version von „[[Datei:EMR7370.zip]]“ hoch wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 742 741 2012-04-28T20:54:22Z Chris 2 lud eine neue Version von „[[Datei:EMR7370.zip]]“ hoch wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 744 742 2012-04-28T21:11:32Z Chris 2 lud eine neue Version von „[[Datei:EMR7370.zip]]“ hoch: Quellcode hinzugefügt Saleae-Dateien in Unterorder geschoben Beulen entfernt. wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 746 744 2012-04-28T21:17:55Z Chris 2 lud eine neue Version von „[[Datei:EMR7370.zip]]“ hoch: korrigiert wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Hauptseite 0 1 745 731 2012-04-28T21:12:53Z Chris 2 wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *12.03.2012 [[EMR7370]] *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] *12.06.2011 [[Maschinenleuchte]] =Updates= *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit e0dc5b9cd71c2650b22feb9a2a30af12e122e134 766 745 2012-05-05T16:33:29Z Chris 2 /* Neues */ wikitext text/x-wiki Willkommen in userer Wiki! Nachdem unsere Schreibwut in letzter Zeit massivst nachgelassen hat, haben wir uns dafür entschieden, auf eine Wiki umzusteigen.<br>Durch die einfachere Handhabe und der niedrigeren Hemmschwelle sollen so unsere Bastelarbeiten schneller den Weg ins Internet finden.<br>Auch ihr seid dazu eingeladen, etwas an der Seite mitzugestalten, indem ihr sie über die Diskussionsseiten kommentiert. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den Artikeln zu kommen. =Neues= *05.05.2012 [[Raspberry Pi IO]] *12.03.2012 [[EMR7370]] *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] =Updates= *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit edc712ab6ca83d3a2d49a73baaf2aed9652deb9a Datei:TCM 17.7degC78%.png 6 296 747 2012-05-02T19:51:13Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:TCM Excel1.png 6 297 748 2012-05-02T20:04:16Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:TCM Excel2.png 6 298 749 2012-05-02T20:04:38Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Tchibo Wetterstation 0 299 750 2012-05-02T20:12:52Z Chris 2 Seite angelegt wikitext text/x-wiki Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? 5257e44fd16c2803f9f543743215ccf125349f98 751 750 2012-05-02T20:28:46Z Chris 2 zur Sicherheit... wikitext text/x-wiki Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Das Wissen über Kanalkodierung, Codeverkettung und Faltungscodes ist bei den Herstellern von solchem Zeug wohl noch nicht angekommen. Hat immerhin den Vorteil, dass es Leute wie ich nicht zu schwer haben. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? Sicher ist zumindest, dass 36 Bit übertragen werden. ==Datenfarm== Nachdem ich über mehrere Abende hinweg sporadisch Werte aufzeichnete (und erzeugte) bekam ich schließlich knapp 50 Datensätze, die ausgewertet werden wollten. Um Copy & Paste-Orgien in Excel zu ersparen, bastelte ich mir ein kleines PHP-Script, das die Zeitstempel in Binärdaten umwandelt: <source lang="php"> function timing2data($filename) { $fh = fopen($filename, "r"); $lasttime = -1; $data = array(); while($line = fgets($fh)) { $time = explode(", ", $line); $time = floatval($time[0]); if($lasttime !== -1) { $val = round(($time - $lasttime) * 1000); switch($val) { case 9: echo "\n"; break; case 0: echo ""; break; case 2: echo "0"; break; case 4: echo "1"; break; default: echo "<".$val.">"; break; } } $lasttime = $time; } fclose($fh); } </source> Hier habe ich auch die Annahme getroffen, dass ein kurzer Puls 0 und ein langer 1 entspricht (ich sollte richtig liegen). Die Ausgabe sieht dann zum Beispiel wie folgt aus: <pre> 000001010000111001111111100100010000 0000010100001110011111<673><19> </pre> die Werte in den spitzen Klammern sind Pausenzeiten, die nicht als 1, 0 oder Sync erkannt wurden und somit Übertragungs-fehler darstellen ee3ec7b99fa6b159b51a65553fee11362373df6c 755 751 2012-05-02T20:58:27Z Chris 2 Nochmal speichern, bevor die Tabelle kommt... wikitext text/x-wiki [[Datei:TCM_vorne.jpg|thumb|Tchibo Wetterstation]] Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. <gallery> Datei:TCM_innen.jpg|Verbasteltes Innenleben der Wetterstation Datei:TCM_sender.jpg|Außensensor/Sender </gallery> Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Das Wissen über Kanalkodierung, Codeverkettung und Faltungscodes ist bei den Herstellern von solchem Zeug wohl noch nicht angekommen. Hat immerhin den Vorteil, dass es Leute wie ich nicht zu schwer haben. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? Sicher ist zumindest, dass 36 Bit übertragen werden. ==Datenfarm== Nachdem ich über mehrere Abende hinweg sporadisch Werte aufzeichnete (und erzeugte) bekam ich schließlich knapp 50 Datensätze, die ausgewertet werden wollten. Um Copy & Paste-Orgien in Excel zu ersparen, bastelte ich mir ein kleines PHP-Script, das die Zeitstempel in Binärdaten umwandelt: <source lang="php"> function timing2data($filename) { $fh = fopen($filename, "r"); $lasttime = -1; $data = array(); while($line = fgets($fh)) { $time = explode(", ", $line); $time = floatval($time[0]); if($lasttime !== -1) { $val = round(($time - $lasttime) * 1000); switch($val) { case 9: echo "\n"; break; case 0: echo ""; break; case 2: echo "0"; break; case 4: echo "1"; break; default: echo "<".$val.">"; break; } } $lasttime = $time; } fclose($fh); } </source> Hier habe ich auch die Annahme getroffen, dass ein kurzer Puls 0 und ein langer 1 entspricht (ich sollte richtig liegen). Die Ausgabe sieht dann zum Beispiel wie folgt aus: <pre> 000001010000111001111111100100010000 0000010100001110011111<673><19> </pre> die Werte in den spitzen Klammern sind Pausenzeiten, die nicht als 1, 0 oder Sync erkannt wurden und somit Übertragungsfehler darstellen. Bei der Auswertung fanden sich dann auch einige Datensätze, bei denen die Auswertung nicht mehr allzu zuverlässig war - also gerade so zwei Übereinstimmungen in den Datenworten. Aber es hat gereicht. In Excel ging dann die Suche nach der Antwort los. ==Beispieldaten== =="Immer" gleich== "Sie kam aus einem kleineren Ort, wo das Motto galt: 'Wenn du nicht weiter weißt, schlachte ein Schwein'" (na, welcher Film war's?) Wie dem auch sei, zu erst einmal kann man die Bits ausschließen, bei denen nichts passiert. Bei meinen Messungen waren dies Nibble 0 und 1. ==Luftfeuchtigkeit== Der Einfachheit halber zuerst mit der Luftfeuchtigkeit, nach der sortiert wurde. Da in einigen Datensätzen die Luftfeuchtigkeit konstant, die Temperatur jedoch unterschiedlich ist, kann man mit relativ wenig Aufwand die zuständigen Bits ermitteln. Dabei hilft es ungemein, die Bits in Gruppen zu unterteilen. Da sich 36 Bits gut durch 4 teilen lassen, habe ich diese Aufteilung gewählt. Excel-Formeln können beim Auseinanderpflücken der Datenworte enorm helfen (siehe Excel-Sheet). Die entsprechenden Spalten waren schnell gefunden: Nibble 6 und 7 71091f5d344178453a1d5dcf354d000dd11416d2 756 755 2012-05-02T21:02:24Z Chris 2 Beispieldaten hinzugefügt, genug für heute wikitext text/x-wiki [[Datei:TCM_vorne.jpg|thumb|Tchibo Wetterstation]] Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. <gallery> Datei:TCM_innen.jpg|Verbasteltes Innenleben der Wetterstation Datei:TCM_sender.jpg|Außensensor/Sender </gallery> Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Das Wissen über Kanalkodierung, Codeverkettung und Faltungscodes ist bei den Herstellern von solchem Zeug wohl noch nicht angekommen. Hat immerhin den Vorteil, dass es Leute wie ich nicht zu schwer haben. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? Sicher ist zumindest, dass 36 Bit übertragen werden. ==Datenfarm== Nachdem ich über mehrere Abende hinweg sporadisch Werte aufzeichnete (und erzeugte) bekam ich schließlich knapp 50 Datensätze, die ausgewertet werden wollten. Um Copy & Paste-Orgien in Excel zu ersparen, bastelte ich mir ein kleines PHP-Script, das die Zeitstempel in Binärdaten umwandelt: <source lang="php"> function timing2data($filename) { $fh = fopen($filename, "r"); $lasttime = -1; $data = array(); while($line = fgets($fh)) { $time = explode(", ", $line); $time = floatval($time[0]); if($lasttime !== -1) { $val = round(($time - $lasttime) * 1000); switch($val) { case 9: echo "\n"; break; case 0: echo ""; break; case 2: echo "0"; break; case 4: echo "1"; break; default: echo "<".$val.">"; break; } } $lasttime = $time; } fclose($fh); } </source> Hier habe ich auch die Annahme getroffen, dass ein kurzer Puls 0 und ein langer 1 entspricht (ich sollte richtig liegen). Die Ausgabe sieht dann zum Beispiel wie folgt aus: <pre> 000001010000111001111111100100010000 0000010100001110011111<673><19> </pre> die Werte in den spitzen Klammern sind Pausenzeiten, die nicht als 1, 0 oder Sync erkannt wurden und somit Übertragungsfehler darstellen. Bei der Auswertung fanden sich dann auch einige Datensätze, bei denen die Auswertung nicht mehr allzu zuverlässig war - also gerade so zwei Übereinstimmungen in den Datenworten. Aber es hat gereicht. In Excel ging dann die Suche nach der Antwort los. ==Beispieldaten== {| class="wikitable sortable" |- ! Temperatur !! Luftfeuchtigkeit !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 |- | 24,1°C || 43% || 0000 || 0101 || 0010 || 1000 || 1111 || 0000 || 1100 || 0010 || 0101 |- | 24,6°C || 45% || 0000 || 0101 || 0010 || 0110 || 1111 || 0000 || 1010 || 0010 || 1100 |- | 17,6°C || 49% || 0000 || 0101 || 0100 || 0000 || 1101 || 0000 || 1001 || 0010 || 1101 |- | 24,8°C || 49% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 1001 || 0010 || 1111 |- | 24,9°C || 49% || 0000 || 0101 || 0100 || 1001 || 1111 || 0000 || 1001 || 0010 || 0111 |- | 24,7°C || 50% || 0000 || 0101 || 0100 || 1110 || 1111 || 0000 || 0000 || 1010 || 0001 |- | 24,8°C || 50% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 0000 || 1010 || 1110 |- | 16,8°C || 51% || 0000 || 0101 || 0100 || 1011 || 0101 || 0000 || 0000 || 1010 || 1110 |- | 24,6°C || 51% || 0000 || 0101 || 0100 || 0110 || 1111 || 0000 || 1000 || 1010 || 0001 |- | 15,7°C || 52% || 0000 || 0101 || 0100 || 1011 || 1001 || 0000 || 0100 || 1010 || 0110 |- | 15,9°C || 52% || 0000 || 0101 || 0100 || 1111 || 1001 || 0000 || 0100 || 1010 || 0010 |- | 16,1°C || 52% || 0000 || 0101 || 0100 || 1000 || 0101 || 0000 || 0100 || 1010 || 1000 |- | 16,3°C || 52% || 0000 || 0101 || 0100 || 1100 || 0101 || 0000 || 0100 || 1010 || 1111 |- | 14,9°C || 53% || 0000 || 0101 || 0100 || 1010 || 1001 || 0000 || 1100 || 1010 || 1011 |- | 15,1°C || 53% || 0000 || 0101 || 0100 || 1110 || 1001 || 0000 || 1100 || 1010 || 1101 |- | 15,5°C || 53% || 0000 || 0101 || 0100 || 1101 || 1001 || 0000 || 1100 || 1010 || 1110 |- |} =="Immer" gleich== "Sie kam aus einem kleineren Ort, wo das Motto galt: 'Wenn du nicht weiter weißt, schlachte ein Schwein'" (na, welcher Film war's?) Wie dem auch sei, zu erst einmal kann man die Bits ausschließen, bei denen nichts passiert. Bei meinen Messungen waren dies Nibble 0 und 1. ==Luftfeuchtigkeit== Der Einfachheit halber zuerst mit der Luftfeuchtigkeit, nach der sortiert wurde. Da in einigen Datensätzen die Luftfeuchtigkeit konstant, die Temperatur jedoch unterschiedlich ist, kann man mit relativ wenig Aufwand die zuständigen Bits ermitteln. Dabei hilft es ungemein, die Bits in Gruppen zu unterteilen. Da sich 36 Bits gut durch 4 teilen lassen, habe ich diese Aufteilung gewählt. Excel-Formeln können beim Auseinanderpflücken der Datenworte enorm helfen (siehe Excel-Sheet). Die entsprechenden Spalten waren schnell gefunden: Nibble 6 und 7 f7564dc616464ddbf5b4578ae6d604146ee63db4 757 756 2012-05-03T21:19:16Z Chris 2 wikitext text/x-wiki [[Datei:TCM_vorne.jpg|thumb|Tchibo Wetterstation]] Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. <gallery> Datei:TCM_innen.jpg|Verbasteltes Innenleben der Wetterstation Datei:TCM_sender.jpg|Außensensor/Sender </gallery> Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Das Wissen über Kanalkodierung, Codeverkettung und Faltungscodes ist bei den Herstellern von solchem Zeug wohl noch nicht angekommen. Hat immerhin den Vorteil, dass es Leute wie ich nicht zu schwer haben. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? Sicher ist zumindest, dass 36 Bit übertragen werden. ==Datenfarm== Nachdem ich über mehrere Abende hinweg sporadisch Werte aufzeichnete (und erzeugte) bekam ich schließlich knapp 50 Datensätze, die ausgewertet werden wollten. Um Copy & Paste-Orgien in Excel zu ersparen, bastelte ich mir ein kleines PHP-Script, das die Zeitstempel in Binärdaten umwandelt: <source lang="php"> function timing2data($filename) { $fh = fopen($filename, "r"); $lasttime = -1; $data = array(); while($line = fgets($fh)) { $time = explode(", ", $line); $time = floatval($time[0]); if($lasttime !== -1) { $val = round(($time - $lasttime) * 1000); switch($val) { case 9: echo "\n"; break; case 0: echo ""; break; case 2: echo "0"; break; case 4: echo "1"; break; default: echo "<".$val.">"; break; } } $lasttime = $time; } fclose($fh); } </source> Hier habe ich auch die Annahme getroffen, dass ein kurzer Puls 0 und ein langer 1 entspricht (ich sollte richtig liegen). Die Ausgabe sieht dann zum Beispiel wie folgt aus: <pre> 000001010000111001111111100100010000 0000010100001110011111<673><19> </pre> die Werte in den spitzen Klammern sind Pausenzeiten, die nicht als 1, 0 oder Sync erkannt wurden und somit Übertragungsfehler darstellen. Bei der Auswertung fanden sich dann auch einige Datensätze, bei denen die Auswertung nicht mehr allzu zuverlässig war - also gerade so zwei Übereinstimmungen in den Datenworten. Aber es hat gereicht. In Excel ging dann die Suche nach der Antwort los. ==Beispieldaten== {| class="wikitable sortable" |- ! Temperatur !! Luftfeuchtigkeit !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 |- | 24,1°C || 43% || 0000 || 0101 || 0010 || 1000 || 1111 || 0000 || 1100 || 0010 || 0101 |- | 24,6°C || 45% || 0000 || 0101 || 0010 || 0110 || 1111 || 0000 || 1010 || 0010 || 1100 |- | 17,6°C || 49% || 0000 || 0101 || 0100 || 0000 || 1101 || 0000 || 1001 || 0010 || 1101 |- | 24,8°C || 49% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 1001 || 0010 || 1111 |- | 24,9°C || 49% || 0000 || 0101 || 0100 || 1001 || 1111 || 0000 || 1001 || 0010 || 0111 |- | 24,7°C || 50% || 0000 || 0101 || 0100 || 1110 || 1111 || 0000 || 0000 || 1010 || 0001 |- | 24,8°C || 50% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 0000 || 1010 || 1110 |- | 16,8°C || 51% || 0000 || 0101 || 0100 || 1011 || 0101 || 0000 || 0000 || 1010 || 1110 |- | 24,6°C || 51% || 0000 || 0101 || 0100 || 0110 || 1111 || 0000 || 1000 || 1010 || 0001 |- | 15,7°C || 52% || 0000 || 0101 || 0100 || 1011 || 1001 || 0000 || 0100 || 1010 || 0110 |- | 15,9°C || 52% || 0000 || 0101 || 0100 || 1111 || 1001 || 0000 || 0100 || 1010 || 0010 |- | 16,1°C || 52% || 0000 || 0101 || 0100 || 1000 || 0101 || 0000 || 0100 || 1010 || 1000 |- | 16,3°C || 52% || 0000 || 0101 || 0100 || 1100 || 0101 || 0000 || 0100 || 1010 || 1111 |- | 14,9°C || 53% || 0000 || 0101 || 0100 || 1010 || 1001 || 0000 || 1100 || 1010 || 1011 |- | 15,1°C || 53% || 0000 || 0101 || 0100 || 1110 || 1001 || 0000 || 1100 || 1010 || 1101 |- | 15,5°C || 53% || 0000 || 0101 || 0100 || 1101 || 1001 || 0000 || 1100 || 1010 || 1110 |- | 11,7°C || 62% || 0000 || 0101 || 0100 || 1010 || 1110 || 0000 || 0100 || 0110 || 1111 |- | 11,8°C || 61% || 0000 || 0101 || 0100 || 0110 || 1110 || 0000 || 1000 || 0110 || 1111 |- | 11,9°C || 61% || 0000 || 0101 || 0100 || 1110 || 1110 || 0000 || 1000 || 0110 || 0111 |- |} =="Immer" gleich== "Sie kam aus einem kleineren Ort, wo das Motto galt: 'Wenn du nicht weiter weißt, schlachte ein Schwein'" (na, welcher Film war's?) Wie dem auch sei, zu erst einmal kann man die Bits ausschließen, bei denen nichts passiert. Bei meinen Messungen waren dies Nibble 0 und 1. ==Luftfeuchtigkeit== Der Einfachheit halber kommt als erstes die Luftfeuchtigkeit dran. Dazu wurde die Excel-Tabelle nach dieser Spalte sortiertz Da in einigen Datensätzen die Luftfeuchtigkeit konstant, die Temperatur jedoch unterschiedlich ist, kann man mit relativ wenig Aufwand die zuständigen Bits ermitteln. Dabei hilft es ungemein, die Bits in Gruppen zu unterteilen. Da sich 36 Bits gut durch 4 teilen lassen, habe ich diese Aufteilung gewählt. Excel-Formeln können beim Auseinanderpflücken der Datenworte enorm helfen (siehe Excel-Sheet). Die entsprechenden Spalten waren schnell gefunden: Nibble 6 und 7 ==Temperatur== Im nachhinein ist der Datenaufbau der Temperatur ebenfalls trivial. Bis man dort hin kommt, können jedoch einige Gehirnwindungen verbogen werden. Auf jeden Fall hilft es auch hier, einen größeren und guten Vorrat an Daten zu haben. Wenn man die Beispieldaten oben nach Temperatur sortiert ("ich hab' da schonmal etwas vorbereitet") sieht man die Temperaturen 11,7, 11,8 und 11,9°C, die sich ideal zum Finden der niederwertigsten Bits eignen. Tatsächlich wird man auch bei Nibble 3 fündig. Allerdings ist die Anordnung der Bits etwas merkwürdig. Die Orientierung ist "verkehrt" herum und die Nachkommastelle scheint einen Offset von 0,2 zu haben. Bei anderen Zeilen scheint diese Regel jedoch keine Gültigkeit zu haben. Also nochmal zurück auf Anfang. Nach längerem herumprobieren bin ich dann auf die Idee gekommen, nicht in Nibbles zu denken, sondern die Bits im zusammengesetztem 32f88b69dd589ec11340034fafc3a7b6a66f96bc 770 757 2012-05-10T20:28:42Z Chris 2 wikitext text/x-wiki [[Datei:TCM_vorne.jpg|thumb|Tchibo Wetterstation]] Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. <gallery> Datei:TCM_innen.jpg|Verbasteltes Innenleben der Wetterstation Datei:TCM_sender.jpg|Außensensor/Sender </gallery> Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Das Wissen über Kanalkodierung, Codeverkettung und Faltungscodes ist bei den Herstellern von solchem Zeug wohl noch nicht angekommen. Hat immerhin den Vorteil, dass es Leute wie ich nicht zu schwer haben. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? Sicher ist zumindest, dass 36 Bit übertragen werden. ==Datenfarm== Nachdem ich über mehrere Abende hinweg sporadisch Werte aufzeichnete (und erzeugte) bekam ich schließlich knapp 50 Datensätze, die ausgewertet werden wollten. Um Copy & Paste-Orgien in Excel zu ersparen, bastelte ich mir ein kleines PHP-Script, das die Zeitstempel in Binärdaten umwandelt: <source lang="php"> function timing2data($filename) { $fh = fopen($filename, "r"); $lasttime = -1; $data = array(); while($line = fgets($fh)) { $time = explode(", ", $line); $time = floatval($time[0]); if($lasttime !== -1) { $val = round(($time - $lasttime) * 1000); switch($val) { case 9: echo "\n"; break; case 0: echo ""; break; case 2: echo "0"; break; case 4: echo "1"; break; default: echo "<".$val.">"; break; } } $lasttime = $time; } fclose($fh); } </source> Hier habe ich auch die Annahme getroffen, dass ein kurzer Puls 0 und ein langer 1 entspricht (ich sollte richtig liegen). Die Ausgabe sieht dann zum Beispiel wie folgt aus: <pre> 000001010000111001111111100100010000 0000010100001110011111<673><19> </pre> die Werte in den spitzen Klammern sind Pausenzeiten, die nicht als 1, 0 oder Sync erkannt wurden und somit Übertragungsfehler darstellen. Bei der Auswertung fanden sich dann auch einige Datensätze, bei denen die Auswertung nicht mehr allzu zuverlässig war - also gerade so zwei Übereinstimmungen in den Datenworten. Aber es hat gereicht. In Excel ging dann die Suche nach der Antwort los. ==Beispieldaten== {| class="wikitable sortable" |- ! Temperatur !! Luftfeuchtigkeit !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 |- | 24,1°C || 43% || 0000 || 0101 || 0010 || 1000 || 1111 || 0000 || 1100 || 0010 || 0101 |- | 24,6°C || 45% || 0000 || 0101 || 0010 || 0110 || 1111 || 0000 || 1010 || 0010 || 1100 |- | 17,6°C || 49% || 0000 || 0101 || 0100 || 0000 || 1101 || 0000 || 1001 || 0010 || 1101 |- | 24,8°C || 49% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 1001 || 0010 || 1111 |- | 24,9°C || 49% || 0000 || 0101 || 0100 || 1001 || 1111 || 0000 || 1001 || 0010 || 0111 |- | 24,7°C || 50% || 0000 || 0101 || 0100 || 1110 || 1111 || 0000 || 0000 || 1010 || 0001 |- | 24,8°C || 50% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 0000 || 1010 || 1110 |- | 24,6°C || 51% || 0000 || 0101 || 0100 || 0110 || 1111 || 0000 || 1000 || 1010 || 0001 |- | 15,7°C || 52% || 0000 || 0101 || 0100 || 1011 || 1001 || 0000 || 0100 || 1010 || 0110 |- | 15,9°C || 52% || 0000 || 0101 || 0100 || 1111 || 1001 || 0000 || 0100 || 1010 || 0010 |- | 16,1°C || 52% || 0000 || 0101 || 0100 || 1000 || 0101 || 0000 || 0100 || 1010 || 1000 |- | 16,3°C || 52% || 0000 || 0101 || 0100 || 1100 || 0101 || 0000 || 0100 || 1010 || 1111 |- | 14,9°C || 53% || 0000 || 0101 || 0100 || 1010 || 1001 || 0000 || 1100 || 1010 || 1011 |- | 15,1°C || 53% || 0000 || 0101 || 0100 || 1110 || 1001 || 0000 || 1100 || 1010 || 1101 |- | 15,5°C || 53% || 0000 || 0101 || 0100 || 1101 || 1001 || 0000 || 1100 || 1010 || 1110 |- | 11,7°C || 62% || 0000 || 0101 || 0100 || 1010 || 1110 || 0000 || 0100 || 0110 || 1111 |- | 11,8°C || 61% || 0000 || 0101 || 0100 || 0110 || 1110 || 0000 || 1000 || 0110 || 1111 |- | 11,9°C || 61% || 0000 || 0101 || 0100 || 1110 || 1110 || 0000 || 1000 || 0110 || 0111 |- | -0,1°C || 89% || 0000 || 0101 || 0000 || 1111 || 1111 || 1111 || 1001 || 0001 || 1110 |- | -0,2°C || 89% || 0000 || 0101 || 0000 || 0111 || 1111 || 1111 || 1001 || 0001 || 0001 |- | -2,5°C || 89% || 0000 || 0101 || 0000 || 1110 || 0111 || 1111 || 1001 || 0001 || 0000 |- |} =="Immer" gleich== "Sie kam aus einem kleineren Ort, wo das Motto galt: 'Wenn du nicht weiter weißt, schlachte ein Schwein'" (na, welcher Film war's?) Wie dem auch sei, zu erst einmal kann man die Bits ausschließen, bei denen nichts passiert. Bei meinen Messungen waren es Nibble 0 und 1. ==Luftfeuchtigkeit== Der Einfachheit halber kommt als erstes die Luftfeuchtigkeit dran. Dazu wurde die Excel-Tabelle nach dieser Spalte sortiert Da in einigen Datensätzen die Luftfeuchtigkeit konstant, die Temperatur jedoch unterschiedlich ist, kann man mit relativ wenig Aufwand die zuständigen Bits ermitteln. Dabei hilft es ungemein, die Bits in Gruppen zu unterteilen. Da sich 36 Bits gut durch 4 teilen lassen, habe ich diese Aufteilung gewählt. Excel-Formeln können beim Auseinanderpflücken der Datenworte enorm helfen (siehe Excel-Sheet). Die entsprechenden Spalten waren schnell gefunden: Nibble 6 und 7. Zum Dekodieren ist es am einfachsten, ähnliche Werte miteinander zu vergleichen. So sieht man z. B. bei den Werten 50% und 51% dass sich bei 51% das höchstwertigste Bit in Nibble 6 ändert. Bei 52% ist nur das zweithöchste Bit aktiv. Ein Muster?! Hilfreich ist hier die Exce-Funktion BININDEZ(), die Binär- in Dezimalwerte umrechnet. Da sich hier aber die höherwertigen Bits "früher" ändern als die niederwertigen ist anzunehmen, dass das Bitmuster verdreht ist. Eine Funktion zum Umkehren von Strings gibt es in Excel anscheinend nicht, allerdings kann man in den Formeln selbstdefinierte Funktionen verwenden. Diese ist in VBA schnell geschrieben: <source lang="VB"> Public Function Reverse(str as String) As String Reverse = StrReverse(str) End Function </source> BININDEZ(Reverse(<Zelle>)) angewendet auf Nibble 6 gibt die Einerstellen aus, Nibble 7 entspricht den Zehnerstellen. Volltreffer! ==Temperatur== Im Nachhinein ist der Datenaufbau der Temperatur ebenfalls trivial. Bis man dort hin kommt, können jedoch einige Gehirnwindungen verbogen werden. Auf jeden Fall hilft es auch hier, einen größeren und guten Vorrat an Daten zu haben. Wenn man die Beispieldaten oben nach Temperatur sortiert ("ich hab' da schonmal etwas vorbereitet") sieht man die Temperaturen 11,7, 11,8 und 11,9°C, die sich ideal zum Finden der niederwertigsten Bits eignen. Tatsächlich wird man auch bei Nibble 3 fündig. Allerdings ist die Anordnung der Bits etwas merkwürdig. Die Orientierung ist "verkehrt" herum und die Nachkommastelle scheint einen Offset von 0,2 zu haben. Bei anderen Zeilen scheint diese Regel jedoch keine Gültigkeit zu haben. Also nochmal zurück auf Anfang. Nach längerem herumprobieren bin ich dann auf die Idee gekommen, nicht in Nibbles zu denken, sondern die Bits im zusammengesetztem 9390bb53477b30afaf4c2012de8323bb818cefc1 771 770 2012-05-10T21:11:17Z Chris 2 wikitext text/x-wiki [[Datei:TCM_vorne.jpg|thumb|Tchibo Wetterstation]] Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. <gallery> Datei:TCM_innen.jpg|Verbasteltes Innenleben der Wetterstation Datei:TCM_sender.jpg|Außensensor/Sender </gallery> Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Das Wissen über Kanalkodierung, Codeverkettung und Faltungscodes ist bei den Herstellern von solchem Zeug wohl noch nicht angekommen. Hat immerhin den Vorteil, dass es Leute wie ich nicht zu schwer haben. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? Sicher ist zumindest, dass 36 Bit übertragen werden. ==Datenfarm== Nachdem ich über mehrere Abende hinweg sporadisch Werte aufzeichnete (und erzeugte) bekam ich schließlich knapp 50 Datensätze, die ausgewertet werden wollten. Um Copy & Paste-Orgien in Excel zu ersparen, bastelte ich mir ein kleines PHP-Script, das die Zeitstempel in Binärdaten umwandelt: <source lang="php"> function timing2data($filename) { $fh = fopen($filename, "r"); $lasttime = -1; $data = array(); while($line = fgets($fh)) { $time = explode(", ", $line); $time = floatval($time[0]); if($lasttime !== -1) { $val = round(($time - $lasttime) * 1000); switch($val) { case 9: echo "\n"; break; case 0: echo ""; break; case 2: echo "0"; break; case 4: echo "1"; break; default: echo "<".$val.">"; break; } } $lasttime = $time; } fclose($fh); } </source> Hier habe ich auch die Annahme getroffen, dass ein kurzer Puls 0 und ein langer 1 entspricht (ich sollte richtig liegen). Die Ausgabe sieht dann zum Beispiel wie folgt aus: <pre> 000001010000111001111111100100010000 0000010100001110011111<673><19> </pre> die Werte in den spitzen Klammern sind Pausenzeiten, die nicht als 1, 0 oder Sync erkannt wurden und somit Übertragungsfehler darstellen. Bei der Auswertung fanden sich dann auch einige Datensätze, bei denen die Auswertung nicht mehr allzu zuverlässig war - also gerade so zwei Übereinstimmungen in den Datenworten. Aber es hat gereicht. In Excel ging dann die Suche nach der Antwort los. ==Beispieldaten== {| class="wikitable sortable" |- ! Temperatur !! Luftfeuchtigkeit !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 |- | 24,1°C || 43% || 0000 || 0101 || 0010 || 1000 || 1111 || 0000 || 1100 || 0010 || 0101 |- | 24,6°C || 45% || 0000 || 0101 || 0010 || 0110 || 1111 || 0000 || 1010 || 0010 || 1100 |- | 24,8°C || 49% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 1001 || 0010 || 1111 |- | 24,9°C || 49% || 0000 || 0101 || 0100 || 1001 || 1111 || 0000 || 1001 || 0010 || 0111 |- | 24,7°C || 50% || 0000 || 0101 || 0100 || 1110 || 1111 || 0000 || 0000 || 1010 || 0001 |- | 24,8°C || 50% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 0000 || 1010 || 1110 |- | 24,6°C || 51% || 0000 || 0101 || 0100 || 0110 || 1111 || 0000 || 1000 || 1010 || 0001 |- | 15,7°C || 52% || 0000 || 0101 || 0100 || 1011 || 1001 || 0000 || 0100 || 1010 || 0110 |- | 15,9°C || 52% || 0000 || 0101 || 0100 || 1111 || 1001 || 0000 || 0100 || 1010 || 0010 |- | 16,1°C || 52% || 0000 || 0101 || 0100 || 1000 || 0101 || 0000 || 0100 || 1010 || 1000 |- | 16,3°C || 52% || 0000 || 0101 || 0100 || 1100 || 0101 || 0000 || 0100 || 1010 || 1111 |- | 14,9°C || 53% || 0000 || 0101 || 0100 || 1010 || 1001 || 0000 || 1100 || 1010 || 1011 |- | 15,1°C || 53% || 0000 || 0101 || 0100 || 1110 || 1001 || 0000 || 1100 || 1010 || 1101 |- | 15,5°C || 53% || 0000 || 0101 || 0100 || 1101 || 1001 || 0000 || 1100 || 1010 || 1110 |- | 11,7°C || 62% || 0000 || 0101 || 0100 || 1010 || 1110 || 0000 || 0100 || 0110 || 1111 |- | 11,8°C || 61% || 0000 || 0101 || 0100 || 0110 || 1110 || 0000 || 1000 || 0110 || 1111 |- | 11,9°C || 61% || 0000 || 0101 || 0100 || 1110 || 1110 || 0000 || 1000 || 0110 || 0111 |- | -0,1°C || 89% || 0000 || 0101 || 0000 || 1111 || 1111 || 1111 || 1001 || 0001 || 1110 |- | -0,2°C || 89% || 0000 || 0101 || 0000 || 0111 || 1111 || 1111 || 1001 || 0001 || 0001 |- | -2,5°C || 89% || 0000 || 0101 || 0000 || 1110 || 0111 || 1111 || 1001 || 0001 || 0000 |- |} =="Immer" gleich== "Sie kam aus einem kleineren Ort, wo das Motto galt: 'Wenn du nicht weiter weißt, schlachte ein Schwein'" (na, welcher Film war's?) Wie dem auch sei, zu erst einmal kann man die Bits ausschließen, bei denen nichts passiert. Bei meinen Messungen waren es Nibble 0 und 1. ==Luftfeuchtigkeit== Der Einfachheit halber kommt als erstes die Luftfeuchtigkeit dran. Dazu wurde die Excel-Tabelle nach dieser Spalte sortiert Da in einigen Datensätzen die Luftfeuchtigkeit konstant, die Temperatur jedoch unterschiedlich ist, kann man mit relativ wenig Aufwand die zuständigen Bits ermitteln. Dabei hilft es ungemein, die Bits in Gruppen zu unterteilen. Da sich 36 Bits gut durch 4 teilen lassen, habe ich diese Aufteilung gewählt. Excel-Formeln können beim Auseinanderpflücken der Datenworte enorm helfen (siehe Excel-Sheet). Die entsprechenden Spalten waren schnell gefunden: Nibble 6 und 7. Zum Dekodieren ist es am einfachsten, ähnliche Werte miteinander zu vergleichen. So sieht man z. B. bei den Werten 50% und 51% dass sich bei 51% das höchstwertigste Bit in Nibble 6 ändert. Bei 52% ist nur das zweithöchste Bit aktiv. Ein Muster?! Hilfreich ist hier die Exce-Funktion BININDEZ(), die Binär- in Dezimalwerte umrechnet. Da sich hier aber die höherwertigen Bits "früher" ändern als die niederwertigen ist anzunehmen, dass das Bitmuster verdreht ist. Eine Funktion zum Umkehren von Strings gibt es in Excel anscheinend nicht, allerdings kann man in den Formeln selbstdefinierte Funktionen verwenden. Diese ist in VBA schnell geschrieben: <source lang="VB"> Public Function Reverse(str as String) As String Reverse = StrReverse(str) End Function </source> BININDEZ(Reverse(<Zelle>)) angewendet auf Nibble 6 gibt die Einerstellen aus, Nibble 7 entspricht den Zehnerstellen. Volltreffer! ==Temperatur== Geht man wie bei der Luftfeuchtigkeit vor und sucht Werte mit der kleinstmöglichen Änderung, landet man sehr schnell bei 11,7, 11,8 und 11,9°C. Da Nibble 0, 1, 6 sowie 7 wegfallen, bleiben nur noch Nibble 3. Nibble 8 ist zwar bei 11,8 und 11,9°C unterschiedlich, bei 11,7 und 11,8°C gleich. Wendet man wieder die Excel-Formel von oben an, kommt man in vielen Fällen auf die richtige Nachkommastelle. 03a5a8ca9c33f804e261c734cffc8e35e58c3a19 772 771 2012-05-11T19:16:10Z Chris 2 Protokollinfos vervollständigt wikitext text/x-wiki [[Datei:TCM_vorne.jpg|thumb|Tchibo Wetterstation]] Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. <gallery> Datei:TCM_innen.jpg|Verbasteltes Innenleben der Wetterstation Datei:TCM_sender.jpg|Außensensor/Sender </gallery> Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Das Wissen über Kanalkodierung, Codeverkettung und Faltungscodes ist bei den Herstellern von solchem Zeug wohl noch nicht angekommen. Hat immerhin den Vorteil, dass es Leute wie ich nicht zu schwer haben. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? Sicher ist zumindest, dass 36 Bit übertragen werden. ==Datenfarm== Nachdem ich über mehrere Abende hinweg sporadisch Werte aufzeichnete (und erzeugte) bekam ich schließlich knapp 50 Datensätze, die ausgewertet werden wollten. Um Copy & Paste-Orgien in Excel zu ersparen, bastelte ich mir ein kleines PHP-Script, das die Zeitstempel in Binärdaten umwandelt: <source lang="php"> function timing2data($filename) { $fh = fopen($filename, "r"); $lasttime = -1; $data = array(); while($line = fgets($fh)) { $time = explode(", ", $line); $time = floatval($time[0]); if($lasttime !== -1) { $val = round(($time - $lasttime) * 1000); switch($val) { case 9: echo "\n"; break; case 0: echo ""; break; case 2: echo "0"; break; case 4: echo "1"; break; default: echo "<".$val.">"; break; } } $lasttime = $time; } fclose($fh); } </source> Hier habe ich auch die Annahme getroffen, dass ein kurzer Puls 0 und ein langer 1 entspricht (ich sollte richtig liegen). Die Ausgabe sieht dann zum Beispiel wie folgt aus: <pre> 000001010000111001111111100100010000 0000010100001110011111<673><19> </pre> die Werte in den spitzen Klammern sind Pausenzeiten, die nicht als 1, 0 oder Sync erkannt wurden und somit Übertragungsfehler darstellen. Bei der Auswertung fanden sich dann auch einige Datensätze, bei denen die Auswertung nicht mehr allzu zuverlässig war - also gerade so zwei Übereinstimmungen in den Datenworten. Aber es hat gereicht. In Excel ging dann die Suche nach der Antwort los. ==Beispieldaten== {| class="wikitable sortable" |- ! Temperatur !! Luftfeuchtigkeit !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 |- | 24,1°C || 43% || 0000 || 0101 || 0010 || 1000 || 1111 || 0000 || 1100 || 0010 || 0101 |- | 24,6°C || 45% || 0000 || 0101 || 0010 || 0110 || 1111 || 0000 || 1010 || 0010 || 1100 |- | 24,8°C || 49% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 1001 || 0010 || 1111 |- | 24,9°C || 49% || 0000 || 0101 || 0100 || 1001 || 1111 || 0000 || 1001 || 0010 || 0111 |- | 24,7°C || 50% || 0000 || 0101 || 0100 || 1110 || 1111 || 0000 || 0000 || 1010 || 0001 |- | 24,8°C || 50% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 0000 || 1010 || 1110 |- | 24,6°C || 51% || 0000 || 0101 || 0100 || 0110 || 1111 || 0000 || 1000 || 1010 || 0001 |- | 15,7°C || 52% || 0000 || 0101 || 0100 || 1011 || 1001 || 0000 || 0100 || 1010 || 0110 |- | 15,9°C || 52% || 0000 || 0101 || 0100 || 1111 || 1001 || 0000 || 0100 || 1010 || 0010 |- | 16,1°C || 52% || 0000 || 0101 || 0100 || 1000 || 0101 || 0000 || 0100 || 1010 || 1000 |- | 16,3°C || 52% || 0000 || 0101 || 0100 || 1100 || 0101 || 0000 || 0100 || 1010 || 1111 |- | 14,9°C || 53% || 0000 || 0101 || 0100 || 1010 || 1001 || 0000 || 1100 || 1010 || 1011 |- | 15,1°C || 53% || 0000 || 0101 || 0100 || 1110 || 1001 || 0000 || 1100 || 1010 || 1101 |- | 15,5°C || 53% || 0000 || 0101 || 0100 || 1101 || 1001 || 0000 || 1100 || 1010 || 1110 |- | 11,7°C || 62% || 0000 || 0101 || 0100 || 1010 || 1110 || 0000 || 0100 || 0110 || 1111 |- | 11,8°C || 61% || 0000 || 0101 || 0100 || 0110 || 1110 || 0000 || 1000 || 0110 || 1111 |- | 11,9°C || 61% || 0000 || 0101 || 0100 || 1110 || 1110 || 0000 || 1000 || 0110 || 0111 |- | -0,1°C || 89% || 0000 || 0101 || 0000 || 1111 || 1111 || 1111 || 1001 || 0001 || 1110 |- | -0,2°C || 89% || 0000 || 0101 || 0000 || 0111 || 1111 || 1111 || 1001 || 0001 || 0001 |- | -2,5°C || 89% || 0000 || 0101 || 0000 || 1110 || 0111 || 1111 || 1001 || 0001 || 0000 |- |} =="Immer" gleich== "Sie kam aus einem kleineren Ort, wo das Motto galt: 'Wenn du nicht weiter weißt, schlachte ein Schwein'" (na, welcher Film war's?) Wie dem auch sei, zu erst einmal kann man die Bits ausschließen, bei denen nichts passiert. Bei meinen Messungen waren es Nibble 0 und 1. ==Luftfeuchtigkeit== Der Einfachheit halber kommt als erstes die Luftfeuchtigkeit dran. Dazu wurde die Excel-Tabelle nach dieser Spalte sortiert Da in einigen Datensätzen die Luftfeuchtigkeit konstant, die Temperatur jedoch unterschiedlich ist, kann man mit relativ wenig Aufwand die zuständigen Bits ermitteln. Dabei hilft es ungemein, die Bits in Gruppen zu unterteilen. Da sich 36 Bits gut durch 4 teilen lassen, habe ich diese Aufteilung gewählt. Excel-Formeln können beim Auseinanderpflücken der Datenworte enorm helfen (siehe Excel-Sheet). Die entsprechenden Spalten waren schnell gefunden: Nibble 6 und 7. Zum Dekodieren ist es am einfachsten, ähnliche Werte miteinander zu vergleichen. So sieht man z. B. bei den Werten 50% und 51% dass sich bei 51% das höchstwertigste Bit in Nibble 6 ändert. Bei 52% ist nur das zweithöchste Bit aktiv. Ein Muster?! Hilfreich ist hier die Exce-Funktion BININDEZ(), die Binär- in Dezimalwerte umrechnet. Da sich hier aber die höherwertigen Bits "früher" ändern als die niederwertigen ist anzunehmen, dass das Bitmuster verdreht ist. Eine Funktion zum Umkehren von Strings gibt es in Excel anscheinend nicht, allerdings kann man in den Formeln selbstdefinierte Funktionen verwenden. Diese ist in VBA schnell geschrieben: <source lang="VB"> Public Function Reverse(str as String) As String Reverse = StrReverse(str) End Function </source> BININDEZ(Reverse(<Zelle>)) angewendet auf Nibble 6 gibt die Einerstellen aus, Nibble 7 entspricht den Zehnerstellen. Volltreffer! ==Temperatur== Geht man wie bei der Luftfeuchtigkeit vor und sucht Werte mit der kleinstmöglichen Änderung, landet man sehr schnell bei 11,7, 11,8 und 11,9°C. Da Nibble 0, 1, 6 sowie 7 wegfallen, bleiben nur noch Nibble 3. Nibble 8 ist zwar bei 11,8 und 11,9°C unterschiedlich, bei 11,7 und 11,8°C gleich. Wendet man wieder die Excel-Formel von oben an, kommt man in vielen Fällen auf die richtige Nachkommastelle. Für eine vollständige Temperatur ist das natürlich noch nicht genug. Wandelt man Nibble 4 auf die gleiche Weise um, und addiert es um 4 Bit verschoben (bzw. mit 16 multipliziert) mit Nibble 3, hat man einen Temperaturbereich von 25,5°C eingeschlossen. Mit Nibble 5 Wächst der Informationsgehalt auf 12 Bit, also auf 2<sup>12</sup>=4096, was 409,5°C (unter Beachtung von 0°C) entsprechen würde. Das ist natürlich Blödsinn - eher schmilzt der Sensor ;-) Der Grund hierfür ist bei den negativen Temperaturen zu finden (die die Anzahl der Bits nochmals bestätigen), die im [[wpde:Zweierkomplement|Zweierkomplement]] übertragen werden. Dadurch verliert man ein Bit an das Vorzeichen, was immerhin noch Temperaturen von -104,8 bis 204,7°C ermöglichen würde. Der Grund für diesen weiten Anzeigebereich dürfte sein, dass das Rechnen mit 4 Bit einfacher ist, als etwas krummes zu verwenden (aber nur eine Annahme). ==Schalter== Der Sender hat, wie oben im Bild gezeigt, einen Kanalwahlschalter. Dieser Kanal müsste also auch bei der Übertragung mitgesendet werden. Hier ist die Ermittlung denkbar einfach: Umschalten und warten, bis Pakete eintreffen. Diese Information ist in den niederwertigsten zwei Bits (bei Beachtung des "Bitreversals") von Nibble 2. Etwas verwirrend ist hierbei, dass die Bits widerum vertauscht sind. ==Synchronisierung== Beim Herumspielen ist mir aufgefallen, dass das manuelle Synchronisieren von Sender und Empfänger zu einem Piepsen der Wetterstation führt. Also muss dies auch übertragen werden. Gleiches wie bei der Schalterstellung: Daten einfangen und vergleichen. Die Information steckt im 3. Bit von Nibble 2 (ebenfalls nach Bitreversal). ==Low Battery== Wenn man schräg auf das Display der Wetterstation schaut, sieht man ein Low-Battery-Symbol neben der Anzeige der Außentemperatur. Auch diesen Zustand kann man sehr einfach erreichen, indem man die Batterien durch ein Labornetzteil ersetzt. Nach Herunterdrehen des Potis erschien tatsächlich das Symbol im Display. Der Logic Analyzer sagt: Nibble 3, niederwertigstes Bit (muss ich Bitreversal noch erwähnen?). ==Rest== Damit wären eigentlich alle nötigen Informationen entschlüsselt. Es bleiben "nur noch" 12 Bit übrig. Wegen der Anordnung vermute ich hinter dem letzten Nibble eine Prüfsumme. Da sich das erste Nibble nur nach Batteriewechsel änderte, gehe ich davon aus, dass es sich um eine Zufällige Bitfolge zur Erweiterung des Addressraum handelt. Die restlichen 4 Bit sind mir bis dato noch gänzlich unbekannt. ==Prüfsumme== Ich mag sie (zumindest bei Reverse Engineering) einfach nicht. Hauptgrund ist, dass es schlichtweg beliebig viele Verfahren gibt, diese zu berechnen. Egal ob CRC, XOR oder eine einfache Summe wie beim [[ECL-Bus-Decoder]] - es ist einfach undankbar, diese zu rekonstruieren. Aber genug gejammert, Sicherheit kostet nunmal Aufwand. Am Anfang habe ich noch per Bruteforce versucht, die Prüfsumme zu ermitteln, indem ich einfach alle Werte ver-CRC-t, mit XOR verprügelt und addiert habe. Das führte nicht unbedingt zum erwünschten Erfolg - wobei ich dazu sagen muss, dass ich dort auch noch mit der Datenfolge in Reinform (also ohne das umdrehen der 4-Bit-Gruppen) gearbeitet habe. Im zweiten Versuch ging ich wieder über Excel (diese Programm wird man einfach nicht los) - dieses mal mit umgedrehten 4er-Gruppen. Dieses Mal war auch der Ansatz etwas anders: ich suchte mir die Datenpakete mit dem geringsten [[wpde:Hammingabstand|Hammingabstand]] - also jene Datenpakete, die möglichst wenige unterschiedliche Bits haben - heraus, was mehr Erfolg versprach. In der Excel-Datei (Name) habe ich meine "Forschungsergebnisse" zusammengefasst. Es handelt sich tatsächlich nur um eine Quersumme der Nibbles 0 bis 7, die im Modulo 16 mit Nibble 8 ver-XOR-t werden. Kommt 15 heraus, ist alles ok, bei jedem anderen Wert hat das Paket was abbekommen. Mit vorletztem Satz ist der Pseudo-Code <pre> summe := Summe(nibble[0 .. 7]) Binär_AND 0x0F WENN (summe Binär_XOR nibble[8]) = 0x0F DANN "Paket ok" ANDERNFALLS "Paket nicht ok" ENDE WENN </pre> gemeint, falls das besser verständlich ist. 633ee73184fde8940b59cc57066a6a68b5be0c32 773 772 2012-05-11T19:59:50Z Chris 2 Jetzt wird es mir langsam zu kalt draußen (und die Mücken zu bissig) - gleich geht's drinnen weiter ;) wikitext text/x-wiki [[Datei:TCM_vorne.jpg|thumb|Tchibo Wetterstation]] Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. <gallery> Datei:TCM_innen.jpg|Verbasteltes Innenleben der Wetterstation Datei:TCM_sender.jpg|Außensensor/Sender </gallery> Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Das Wissen über Kanalkodierung, Codeverkettung und Faltungscodes ist bei den Herstellern von solchem Zeug wohl noch nicht angekommen. Hat immerhin den Vorteil, dass es Leute wie ich nicht zu schwer haben. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? Sicher ist zumindest, dass 36 Bit übertragen werden. ==Datenfarm== Nachdem ich über mehrere Abende hinweg sporadisch Werte aufzeichnete (und erzeugte) bekam ich schließlich knapp 50 Datensätze, die ausgewertet werden wollten. Um Copy & Paste-Orgien in Excel zu ersparen, bastelte ich mir ein kleines PHP-Script, das die Zeitstempel in Binärdaten umwandelt: <source lang="php"> function timing2data($filename) { $fh = fopen($filename, "r"); $lasttime = -1; $data = array(); while($line = fgets($fh)) { $time = explode(", ", $line); $time = floatval($time[0]); if($lasttime !== -1) { $val = round(($time - $lasttime) * 1000); switch($val) { case 9: echo "\n"; break; case 0: echo ""; break; case 2: echo "0"; break; case 4: echo "1"; break; default: echo "<".$val.">"; break; } } $lasttime = $time; } fclose($fh); } </source> Hier habe ich auch die Annahme getroffen, dass ein kurzer Puls 0 und ein langer 1 entspricht (ich sollte richtig liegen). Die Ausgabe sieht dann zum Beispiel wie folgt aus: <pre> 000001010000111001111111100100010000 0000010100001110011111<673><19> </pre> die Werte in den spitzen Klammern sind Pausenzeiten, die nicht als 1, 0 oder Sync erkannt wurden und somit Übertragungsfehler darstellen. Bei der Auswertung fanden sich dann auch einige Datensätze, bei denen die Auswertung nicht mehr allzu zuverlässig war - also gerade so zwei Übereinstimmungen in den Datenworten. Aber es hat gereicht. In Excel ging dann die Suche nach der Antwort los. ==Beispieldaten== {| class="wikitable sortable" |- ! Temperatur !! Luftfeuchtigkeit !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 |- | 24,1°C || 43% || 0000 || 0101 || 0010 || 1000 || 1111 || 0000 || 1100 || 0010 || 0101 |- | 24,6°C || 45% || 0000 || 0101 || 0010 || 0110 || 1111 || 0000 || 1010 || 0010 || 1100 |- | 24,8°C || 49% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 1001 || 0010 || 1111 |- | 24,9°C || 49% || 0000 || 0101 || 0100 || 1001 || 1111 || 0000 || 1001 || 0010 || 0111 |- | 24,7°C || 50% || 0000 || 0101 || 0100 || 1110 || 1111 || 0000 || 0000 || 1010 || 0001 |- | 24,8°C || 50% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 0000 || 1010 || 1110 |- | 24,6°C || 51% || 0000 || 0101 || 0100 || 0110 || 1111 || 0000 || 1000 || 1010 || 0001 |- | 15,7°C || 52% || 0000 || 0101 || 0100 || 1011 || 1001 || 0000 || 0100 || 1010 || 0110 |- | 15,9°C || 52% || 0000 || 0101 || 0100 || 1111 || 1001 || 0000 || 0100 || 1010 || 0010 |- | 16,1°C || 52% || 0000 || 0101 || 0100 || 1000 || 0101 || 0000 || 0100 || 1010 || 1000 |- | 16,3°C || 52% || 0000 || 0101 || 0100 || 1100 || 0101 || 0000 || 0100 || 1010 || 1111 |- | 14,9°C || 53% || 0000 || 0101 || 0100 || 1010 || 1001 || 0000 || 1100 || 1010 || 1011 |- | 15,1°C || 53% || 0000 || 0101 || 0100 || 1110 || 1001 || 0000 || 1100 || 1010 || 1101 |- | 15,5°C || 53% || 0000 || 0101 || 0100 || 1101 || 1001 || 0000 || 1100 || 1010 || 1110 |- | 11,7°C || 62% || 0000 || 0101 || 0100 || 1010 || 1110 || 0000 || 0100 || 0110 || 1111 |- | 11,8°C || 61% || 0000 || 0101 || 0100 || 0110 || 1110 || 0000 || 1000 || 0110 || 1111 |- | 11,9°C || 61% || 0000 || 0101 || 0100 || 1110 || 1110 || 0000 || 1000 || 0110 || 0111 |- | -0,1°C || 89% || 0000 || 0101 || 0000 || 1111 || 1111 || 1111 || 1001 || 0001 || 1110 |- | -0,2°C || 89% || 0000 || 0101 || 0000 || 0111 || 1111 || 1111 || 1001 || 0001 || 0001 |- | -2,5°C || 89% || 0000 || 0101 || 0000 || 1110 || 0111 || 1111 || 1001 || 0001 || 0000 |- |} =="Immer" gleich== "Sie kam aus einem kleineren Ort, wo das Motto galt: 'Wenn du nicht weiter weißt, schlachte ein Schwein'" (na, welcher Film war's?) Wie dem auch sei, zu erst einmal kann man die Bits ausschließen, bei denen nichts passiert. Bei meinen Messungen waren es Nibble 0 und 1. ==Luftfeuchtigkeit== Der Einfachheit halber kommt als erstes die Luftfeuchtigkeit dran. Dazu wurde die Excel-Tabelle nach dieser Spalte sortiert Da in einigen Datensätzen die Luftfeuchtigkeit konstant, die Temperatur jedoch unterschiedlich ist, kann man mit relativ wenig Aufwand die zuständigen Bits ermitteln. Dabei hilft es ungemein, die Bits in Gruppen zu unterteilen. Da sich 36 Bits gut durch 4 teilen lassen, habe ich diese Aufteilung gewählt. Excel-Formeln können beim Auseinanderpflücken der Datenworte enorm helfen (siehe Excel-Sheet). Die entsprechenden Spalten waren schnell gefunden: Nibble 6 und 7. Zum Dekodieren ist es am einfachsten, ähnliche Werte miteinander zu vergleichen. So sieht man z. B. bei den Werten 50% und 51% dass sich bei 51% das höchstwertigste Bit in Nibble 6 ändert. Bei 52% ist nur das zweithöchste Bit aktiv. Ein Muster?! Hilfreich ist hier die Exce-Funktion BININDEZ(), die Binär- in Dezimalwerte umrechnet. Da sich hier aber die höherwertigen Bits "früher" ändern als die niederwertigen ist anzunehmen, dass das Bitmuster verdreht ist. Eine Funktion zum Umkehren von Strings gibt es in Excel anscheinend nicht, allerdings kann man in den Formeln selbstdefinierte Funktionen verwenden. Diese ist in VBA schnell geschrieben: <source lang="VB"> Public Function Reverse(str as String) As String Reverse = StrReverse(str) End Function </source> BININDEZ(Reverse(<Zelle>)) angewendet auf Nibble 6 gibt die Einerstellen aus, Nibble 7 entspricht den Zehnerstellen. Volltreffer! ==Temperatur== Geht man wie bei der Luftfeuchtigkeit vor und sucht Werte mit der kleinstmöglichen Änderung, landet man sehr schnell bei 11,7, 11,8 und 11,9°C. Da Nibble 0, 1, 6 sowie 7 wegfallen, bleiben nur noch Nibble 3. Nibble 8 ist zwar bei 11,8 und 11,9°C unterschiedlich, bei 11,7 und 11,8°C gleich. Wendet man wieder die Excel-Formel von oben an, kommt man in vielen Fällen auf die richtige Nachkommastelle. Für eine vollständige Temperatur ist das natürlich noch nicht genug. Wandelt man Nibble 4 auf die gleiche Weise um, und addiert es um 4 Bit verschoben (bzw. mit 16 multipliziert) mit Nibble 3, hat man einen Temperaturbereich von 25,5°C eingeschlossen. Mit Nibble 5 Wächst der Informationsgehalt auf 12 Bit, also auf 2<sup>12</sup>=4096, was 409,5°C (unter Beachtung von 0°C) entsprechen würde. Das ist natürlich Blödsinn - eher schmilzt der Sensor ;-) Der Grund hierfür ist bei den negativen Temperaturen zu finden (die die Anzahl der Bits nochmals bestätigen), die im [[wpde:Zweierkomplement|Zweierkomplement]] übertragen werden. Dadurch verliert man ein Bit an das Vorzeichen, was immerhin noch Temperaturen von -104,8 bis 204,7°C ermöglichen würde. Der Grund für diesen weiten Anzeigebereich dürfte sein, dass das Rechnen mit 4 Bit einfacher ist, als etwas krummes zu verwenden (aber nur eine Annahme). ==Schalter== Der Sender hat, wie oben im Bild gezeigt, einen Kanalwahlschalter. Dieser Kanal müsste also auch bei der Übertragung mitgesendet werden. Hier ist die Ermittlung denkbar einfach: Umschalten und warten, bis Pakete eintreffen. Diese Information ist in den niederwertigsten zwei Bits (bei Beachtung des "Bitreversals") von Nibble 2. Etwas verwirrend ist hierbei, dass die Bits widerum vertauscht sind. ==Synchronisierung== Beim Herumspielen ist mir aufgefallen, dass das manuelle Synchronisieren von Sender und Empfänger zu einem Piepsen der Wetterstation führt. Also muss dies auch übertragen werden. Gleiches wie bei der Schalterstellung: Daten einfangen und vergleichen. Die Information steckt im 3. Bit von Nibble 2 (ebenfalls nach Bitreversal). ==Low Battery== Wenn man schräg auf das Display der Wetterstation schaut, sieht man ein Low-Battery-Symbol neben der Anzeige der Außentemperatur. Auch diesen Zustand kann man sehr einfach erreichen, indem man die Batterien durch ein Labornetzteil ersetzt. Nach Herunterdrehen des Potis erschien tatsächlich das Symbol im Display. Der Logic Analyzer sagt: Nibble 3, niederwertigstes Bit (muss ich Bitreversal noch erwähnen?). ==Rest== Damit wären eigentlich alle nötigen Informationen entschlüsselt. Es bleiben "nur noch" 12 Bit übrig. Wegen der Anordnung vermute ich hinter dem letzten Nibble eine Prüfsumme. Da sich das erste Nibble nur nach Batteriewechsel änderte, gehe ich davon aus, dass es sich um eine Zufällige Bitfolge zur Erweiterung des Addressraum handelt. Die restlichen 4 Bit sind mir bis dato noch gänzlich unbekannt. ==Prüfsumme== Ich mag sie (zumindest bei Reverse Engineering) einfach nicht. Hauptgrund ist, dass es schlichtweg beliebig viele Verfahren gibt, diese zu berechnen. Egal ob CRC, XOR oder eine einfache Summe wie beim [[ECL-Bus-Decoder]] - es ist einfach undankbar, diese zu rekonstruieren. Aber genug gejammert, Sicherheit kostet nunmal Aufwand. Am Anfang habe ich noch per Bruteforce versucht, die Prüfsumme zu ermitteln, indem ich einfach alle Werte ver-CRC-t, mit XOR verprügelt und addiert habe. Das führte nicht unbedingt zum erwünschten Erfolg - wobei ich dazu sagen muss, dass ich dort auch noch mit der Datenfolge in Reinform (also ohne das umdrehen der 4-Bit-Gruppen) gearbeitet habe. Im zweiten Versuch ging ich wieder über Excel (diese Programm wird man einfach nicht los) - dieses mal mit umgedrehten 4er-Gruppen. Dieses Mal war auch der Ansatz etwas anders: ich suchte mir die Datenpakete mit dem geringsten [[wpde:Hammingabstand|Hammingabstand]] - also jene Datenpakete, die möglichst wenige unterschiedliche Bits haben - heraus, was mehr Erfolg versprach. In der Excel-Datei (Name) habe ich meine "Forschungsergebnisse" zusammengefasst. Es handelt sich tatsächlich nur um eine Quersumme der Nibbles 0 bis 7, die im Modulo 16 mit Nibble 8 ver-XOR-t werden. Kommt 15 heraus, ist alles ok, bei jedem anderen Wert hat das Paket was abbekommen. Mit vorletztem Satz ist der Pseudo-Code <pre> summe := Summe(nibble[0 .. 7]) Binär_AND 0x0F WENN (summe Binär_XOR nibble[8]) = 0x0F DANN "Paket ok" ANDERNFALLS "Paket nicht ok" ENDE WENN </pre> gemeint, falls das besser verständlich ist. =Software= Um weder Logic-Analyzer noch PC für die Erfassung der Außentemperatur und Luftfeuchte zu bemühen, soll der Code wieder auf einen Mikrocontroller. Aus gewohnheit kommt wieder ein AVR ATmega8 zum Einsatz. Zur bequemen Auswertung habe ich dieses mal den ICP (Input Compare Pin) bemüht. Da ich bis jetzt keine größere Erfahrung mit dem Komparator hatte, inspirierte ich mich ein wenig an der Atmel AppNote [http://www.atmel.com/Images/doc8014.pdf AVR135]. Diese beschreibt die Auswertung des Duty-Cylces eines PWM-Signals, also genau das, was man für den Empfänger braucht. Um einen ungefähren Ausgangswert zu haben, eine kleine Rechnung: das kürzeste Signal hat eine Pulsweite von etwa 2ms, das längste 9ms. Diese müssen also zuverlässig erkannt werden. Der AVR läuft mit 12MHz (der Quarz steckt noch vom [[EMR7370]] im Breadboard), wodurch der AVR eine Zyklusdauer von 83,33ns entspricht. 8ms enstprechen genau 96000 Taktzyklen - etwas viel für den 16-Bit-Timer. Mit dem großzügigen Vorteiler 1024 kommt man auf knapp 94. Bleib noch die Frage, ob die 2 und 4ms sauber unterschieden werden können. 2ms entspricht 23 Timerzyklen, 4ms 47 - also durchaus brauchbare Werte. Zur Bestätigung dieser Theorie baute ich die AppNote so um, dass sie mir die Zählerstände für die jeweiligen High-Zyklen ausgab - mit durchschlagendem Erfolg. Zwar wackelten die Werte ein wenig, das aber im mehr als vertretbaren Rahmen. Zur Auswertung wird eine kleine Statemachine verwendet, was sich schlimmer anhört, als es eigentlich ist. In einer Variable wird der Zustand des Empfangs geschrieben: Warten auf Paket, Synchronisiert + Datenempfang, Fertig. Wird ein Paket empfangen, werden die Bits in ein Array geschrieben und ein Zähler hochgezählt. Ist dieser bei 36 (der Anzahl der Bits) angelangt, geht der Empfänger in den Zustand Fertig über und keine weiteren Bits werden eingelesen. Ist die Auswertung abgeschlossen, geht der Zustand in "Warten" zurück. Wird eine Pulslänge empfangen, die weder einer 1, 0 noch Sync entspricht, wird der Automat ebenfalls in Warten zurückgesetzt, wodurch die zuletzt empfangenen Bits verworfen werden. ==Der Trick mit den Bits== Zunächst habe ich Bits einfach wie sie gekommen sind in den Array geschrieben und erst zur Auswertung in die richtige Reihenfolge gebracht. Das kostet Zeit und Speicher, was sich durch geschickten Code minimieren lässt. Schaut man sich das Bitreversal genauer an, {| class="wikitable" |- ! Bit mit Nr. !! (Binär) !! soll in Spalte !! (Binär) | 0 || 0000 || 4 || 0100 |- | 1 || 0001 || 5 || 0101 |- | 2 || 0010 || 6 || 0110 |- | 3 || 0011 || 7 || 0111 |- | 4 || 0100 || 0 || 0000 |- | 5 || 0101 || 1 || 0001 |- | 6 || 0110 || 2 || 0010 |- | 7 || 0111 || 3 || 0011 |} sieht man, dass man für die Zuordnung eigentlich nur Bit 3 kippen muss. Alle Bits ab Bit 4 kann man für die Zuordnung der Bytes verwenden, was im Quellcode wie folgt aussieht: <source lang="c"> if(bit == TCM_BIT_1) { uint8_t bytepos = tcm_pos >> 3; uint8_t bitpos = (tcm_pos ^ 4) & 7; tcm_bits[bytepos] |= 1<<bitpos; } </source> Das spart wenn ich mich recht erinnere knapp 40 Byte und wahrscheinlich einige Zyklen in der CPU. 87d07d3d1690252c509a71449ce36d55108c45bd 774 773 2012-05-12T15:34:07Z Chris 2 Zusammenfassung wikitext text/x-wiki [[Datei:TCM_vorne.jpg|thumb|Tchibo Wetterstation]] Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. <gallery> Datei:TCM_innen.jpg|Verbasteltes Innenleben der Wetterstation Datei:TCM_sender.jpg|Außensensor/Sender </gallery> Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Das Wissen über Kanalkodierung, Codeverkettung und Faltungscodes ist bei den Herstellern von solchem Zeug wohl noch nicht angekommen. Hat immerhin den Vorteil, dass es Leute wie ich nicht zu schwer haben. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? Sicher ist zumindest, dass 36 Bit übertragen werden. ==Datenfarm== Nachdem ich über mehrere Abende hinweg sporadisch Werte aufzeichnete (und erzeugte) bekam ich schließlich knapp 50 Datensätze, die ausgewertet werden wollten. Um Copy & Paste-Orgien in Excel zu ersparen, bastelte ich mir ein kleines PHP-Script, das die Zeitstempel in Binärdaten umwandelt: <source lang="php"> function timing2data($filename) { $fh = fopen($filename, "r"); $lasttime = -1; $data = array(); while($line = fgets($fh)) { $time = explode(", ", $line); $time = floatval($time[0]); if($lasttime !== -1) { $val = round(($time - $lasttime) * 1000); switch($val) { case 9: echo "\n"; break; case 0: echo ""; break; case 2: echo "0"; break; case 4: echo "1"; break; default: echo "<".$val.">"; break; } } $lasttime = $time; } fclose($fh); } </source> Hier habe ich auch die Annahme getroffen, dass ein kurzer Puls 0 und ein langer 1 entspricht (ich sollte richtig liegen). Die Ausgabe sieht dann zum Beispiel wie folgt aus: <pre> 000001010000111001111111100100010000 0000010100001110011111<673><19> </pre> die Werte in den spitzen Klammern sind Pausenzeiten, die nicht als 1, 0 oder Sync erkannt wurden und somit Übertragungsfehler darstellen. Bei der Auswertung fanden sich dann auch einige Datensätze, bei denen die Auswertung nicht mehr allzu zuverlässig war - also gerade so zwei Übereinstimmungen in den Datenworten. Aber es hat gereicht. In Excel ging dann die Suche nach der Antwort los. ==Beispieldaten== {| class="wikitable sortable" |- ! Temperatur !! Luftfeuchtigkeit !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 |- | 24,1°C || 43% || 0000 || 0101 || 0010 || 1000 || 1111 || 0000 || 1100 || 0010 || 0101 |- | 24,6°C || 45% || 0000 || 0101 || 0010 || 0110 || 1111 || 0000 || 1010 || 0010 || 1100 |- | 24,8°C || 49% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 1001 || 0010 || 1111 |- | 24,9°C || 49% || 0000 || 0101 || 0100 || 1001 || 1111 || 0000 || 1001 || 0010 || 0111 |- | 24,7°C || 50% || 0000 || 0101 || 0100 || 1110 || 1111 || 0000 || 0000 || 1010 || 0001 |- | 24,8°C || 50% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 0000 || 1010 || 1110 |- | 24,6°C || 51% || 0000 || 0101 || 0100 || 0110 || 1111 || 0000 || 1000 || 1010 || 0001 |- | 15,7°C || 52% || 0000 || 0101 || 0100 || 1011 || 1001 || 0000 || 0100 || 1010 || 0110 |- | 15,9°C || 52% || 0000 || 0101 || 0100 || 1111 || 1001 || 0000 || 0100 || 1010 || 0010 |- | 16,1°C || 52% || 0000 || 0101 || 0100 || 1000 || 0101 || 0000 || 0100 || 1010 || 1000 |- | 16,3°C || 52% || 0000 || 0101 || 0100 || 1100 || 0101 || 0000 || 0100 || 1010 || 1111 |- | 14,9°C || 53% || 0000 || 0101 || 0100 || 1010 || 1001 || 0000 || 1100 || 1010 || 1011 |- | 15,1°C || 53% || 0000 || 0101 || 0100 || 1110 || 1001 || 0000 || 1100 || 1010 || 1101 |- | 15,5°C || 53% || 0000 || 0101 || 0100 || 1101 || 1001 || 0000 || 1100 || 1010 || 1110 |- | 11,7°C || 62% || 0000 || 0101 || 0100 || 1010 || 1110 || 0000 || 0100 || 0110 || 1111 |- | 11,8°C || 61% || 0000 || 0101 || 0100 || 0110 || 1110 || 0000 || 1000 || 0110 || 1111 |- | 11,9°C || 61% || 0000 || 0101 || 0100 || 1110 || 1110 || 0000 || 1000 || 0110 || 0111 |- | -0,1°C || 89% || 0000 || 0101 || 0000 || 1111 || 1111 || 1111 || 1001 || 0001 || 1110 |- | -0,2°C || 89% || 0000 || 0101 || 0000 || 0111 || 1111 || 1111 || 1001 || 0001 || 0001 |- | -2,5°C || 89% || 0000 || 0101 || 0000 || 1110 || 0111 || 1111 || 1001 || 0001 || 0000 |- |} =="Immer" gleich== "Sie kam aus einem kleineren Ort, wo das Motto galt: 'Wenn du nicht weiter weißt, schlachte ein Schwein'" (na, welcher Film war's?) Wie dem auch sei, zu erst einmal kann man die Bits ausschließen, bei denen nichts passiert. Bei meinen Messungen waren es Nibble 0 und 1. ==Luftfeuchtigkeit== Der Einfachheit halber kommt als erstes die Luftfeuchtigkeit dran. Dazu wurde die Excel-Tabelle nach dieser Spalte sortiert Da in einigen Datensätzen die Luftfeuchtigkeit konstant, die Temperatur jedoch unterschiedlich ist, kann man mit relativ wenig Aufwand die zuständigen Bits ermitteln. Dabei hilft es ungemein, die Bits in Gruppen zu unterteilen. Da sich 36 Bits gut durch 4 teilen lassen, habe ich diese Aufteilung gewählt. Excel-Formeln können beim Auseinanderpflücken der Datenworte enorm helfen (siehe Excel-Sheet). Die entsprechenden Spalten waren schnell gefunden: Nibble 6 und 7. Zum Dekodieren ist es am einfachsten, ähnliche Werte miteinander zu vergleichen. So sieht man z. B. bei den Werten 50% und 51% dass sich bei 51% das höchstwertigste Bit in Nibble 6 ändert. Bei 52% ist nur das zweithöchste Bit aktiv. Ein Muster?! Hilfreich ist hier die Exce-Funktion BININDEZ(), die Binär- in Dezimalwerte umrechnet. Da sich hier aber die höherwertigen Bits "früher" ändern als die niederwertigen ist anzunehmen, dass das Bitmuster verdreht ist. Eine Funktion zum Umkehren von Strings gibt es in Excel anscheinend nicht, allerdings kann man in den Formeln selbstdefinierte Funktionen verwenden. Diese ist in VBA schnell geschrieben: <source lang="VB"> Public Function Reverse(str as String) As String Reverse = StrReverse(str) End Function </source> BININDEZ(Reverse(<Zelle>)) angewendet auf Nibble 6 gibt die Einerstellen aus, Nibble 7 entspricht den Zehnerstellen. Volltreffer! ==Temperatur== Geht man wie bei der Luftfeuchtigkeit vor und sucht Werte mit der kleinstmöglichen Änderung, landet man sehr schnell bei 11,7, 11,8 und 11,9°C. Da Nibble 0, 1, 6 sowie 7 wegfallen, bleiben nur noch Nibble 3. Nibble 8 ist zwar bei 11,8 und 11,9°C unterschiedlich, bei 11,7 und 11,8°C gleich. Wendet man wieder die Excel-Formel von oben an, kommt man in vielen Fällen auf die richtige Nachkommastelle. Für eine vollständige Temperatur ist das natürlich noch nicht genug. Wandelt man Nibble 4 auf die gleiche Weise um, und addiert es um 4 Bit verschoben (bzw. mit 16 multipliziert) mit Nibble 3, hat man einen Temperaturbereich von 25,5°C eingeschlossen. Mit Nibble 5 Wächst der Informationsgehalt auf 12 Bit, also auf 2<sup>12</sup>=4096, was 409,5°C (unter Beachtung von 0°C) entsprechen würde. Das ist natürlich Blödsinn - eher schmilzt der Sensor ;-) Der Grund hierfür ist bei den negativen Temperaturen zu finden (die die Anzahl der Bits nochmals bestätigen), die im [[wpde:Zweierkomplement|Zweierkomplement]] übertragen werden. Dadurch verliert man ein Bit an das Vorzeichen, was immerhin noch Temperaturen von -104,8 bis 204,7°C ermöglichen würde. Der Grund für diesen weiten Anzeigebereich dürfte sein, dass das Rechnen mit 4 Bit einfacher ist, als etwas krummes zu verwenden (aber nur eine Annahme). ==Schalter== Der Sender hat, wie oben im Bild gezeigt, einen Kanalwahlschalter. Dieser Kanal müsste also auch bei der Übertragung mitgesendet werden. Hier ist die Ermittlung denkbar einfach: Umschalten und warten, bis Pakete eintreffen. Diese Information ist in den niederwertigsten zwei Bits (bei Beachtung des "Bitreversals") von Nibble 2. Etwas verwirrend ist hierbei, dass die Bits widerum vertauscht sind. ==Synchronisierung== Beim Herumspielen ist mir aufgefallen, dass das manuelle Synchronisieren von Sender und Empfänger zu einem Piepsen der Wetterstation führt. Also muss dies auch übertragen werden. Gleiches wie bei der Schalterstellung: Daten einfangen und vergleichen. Die Information steckt im 3. Bit von Nibble 2 (ebenfalls nach Bitreversal). ==Low Battery== Wenn man schräg auf das Display der Wetterstation schaut, sieht man ein Low-Battery-Symbol neben der Anzeige der Außentemperatur. Auch diesen Zustand kann man sehr einfach erreichen, indem man die Batterien durch ein Labornetzteil ersetzt. Nach Herunterdrehen des Potis erschien tatsächlich das Symbol im Display. Der Logic Analyzer sagt: Nibble 3, niederwertigstes Bit (muss ich Bitreversal noch erwähnen?). ==Rest== Damit wären eigentlich alle nötigen Informationen entschlüsselt. Es bleiben "nur noch" 12 Bit übrig. Wegen der Anordnung vermute ich hinter dem letzten Nibble eine Prüfsumme. Da sich das erste Nibble nur nach Batteriewechsel änderte, gehe ich davon aus, dass es sich um eine Zufällige Bitfolge zur Erweiterung des Addressraum handelt. Die restlichen 4 Bit sind mir bis dato noch gänzlich unbekannt. ==Prüfsumme== Ich mag sie (zumindest bei Reverse Engineering) einfach nicht. Hauptgrund ist, dass es schlichtweg beliebig viele Verfahren gibt, diese zu berechnen. Egal ob CRC, XOR oder eine einfache Summe wie beim [[ECL-Bus-Decoder]] - es ist einfach undankbar, diese zu rekonstruieren. Aber genug gejammert, Sicherheit kostet nunmal Aufwand. Am Anfang habe ich noch per Bruteforce versucht, die Prüfsumme zu ermitteln, indem ich einfach alle Werte ver-CRC-t, mit XOR verprügelt und addiert habe. Das führte nicht unbedingt zum erwünschten Erfolg - wobei ich dazu sagen muss, dass ich dort auch noch mit der Datenfolge in Reinform (also ohne das umdrehen der 4-Bit-Gruppen) gearbeitet habe. Im zweiten Versuch ging ich wieder über Excel (diese Programm wird man einfach nicht los) - dieses mal mit umgedrehten 4er-Gruppen. Dieses Mal war auch der Ansatz etwas anders: ich suchte mir die Datenpakete mit dem geringsten [[wpde:Hammingabstand|Hammingabstand]] - also jene Datenpakete, die möglichst wenige unterschiedliche Bits haben - heraus, was mehr Erfolg versprach. In der Excel-Datei (Name) habe ich meine "Forschungsergebnisse" zusammengefasst. Es handelt sich tatsächlich nur um eine Quersumme der Nibbles 0 bis 7, die im Modulo 16 mit Nibble 8 ver-XOR-t werden. Kommt 15 heraus, ist alles ok, bei jedem anderen Wert hat das Paket was abbekommen. Mit vorletztem Satz ist der Pseudo-Code <pre> summe := Summe(nibble[0 .. 7]) Binär_AND 0x0F WENN (summe Binär_XOR nibble[8]) = 0x0F DANN "Paket ok" ANDERNFALLS "Paket nicht ok" ENDE WENN </pre> gemeint, falls das besser verständlich ist. ==Zusammenfassung== {| class="wikitable" | '''Nibbles''' | colspan="4" align="center" | Nibble 0 | colspan="4" align="center" | Nibble 1 | colspan="4" align="center" | Nibble 2 | colspan="4" align="center" | Nibble 3 | colspan="4" align="center" | Nibble 4 | colspan="4" align="center" | Nibble 5 | colspan="4" align="center" | Nibble 6 | colspan="4" align="center" | Nibble 7 | colspan="4" align="center" | Nibble 8 |- | '''Empfangen''' | 0 || 0 || 0 || 0 || 0 || 1 || 0 || 1 || 0 || 1 || 0 || 0 || 1 || 1 || 0 || 0 || 1 || 1 || 1 || 1 || 0 || 0 || 0 || 0 || 0 || 0 || 1 || 0 || 1 || 0 || 1 || 0 || 0 || 0 || 0 || 1 |- | '''Bit-Reversal''' | 0 || 0 || 0 || 0 || 1 || 0 || 1 || 0 || 0 || 0 || 1 || 0 || 0 || 0 || 1 || 1 || 1 || 1 || 1 || 1 || 0 || 0 || 0 || 0 || 0 || 1 || 0 || 0 || 0 || 1 || 0 || 1 || 1 || 0 || 0 || 0 |- | '''Bezeichnung''' | colspan="4" align="center" | Adresse | ? | Sync | colspan="2" align="center" | Schalter | ? | ? | ? | Low Bat | colspan="4" align="center" | Temp 0 | colspan="4" align="center" | Temp 1 | colspan="4" align="center" | Temp 2 | colspan="4" align="center" | Hygro 0 | colspan="4" align="center" | Hygro 1 | colspan="4" align="center" | Prüfsumme |- | '''Bedeutung''' | colspan="4" align="center" | 0 | ? | nein | colspan="2" align="center" | 1 | ? | ? | ? | nein | colspan="4" align="center" | 3 | colspan="4" align="center" | 15 | colspan="4" align="center" | 0 | colspan="4" align="center" | 4 | colspan="4" align="center" | 5 | colspan="4" align="center" | 8 |} Die Temperatur lässt sich mit (3 + 15 * 16 + 0 * 256)/10 = 24,3 berechnen. Die Luftfeuchte entspricht 54% Die Prüfsumme hier ist 8, also müssen die restlichen Bytes 7 entsprechen: (0 + 10 + 2 + 3 + 15 + 0 + 4 + 5) AND 15 = 39 AND 15 = 7 7 XOR 8 = 15 => korrekt. =Software= Um weder Logic-Analyzer noch PC für die Erfassung der Außentemperatur und Luftfeuchte zu bemühen, soll der Code wieder auf einen Mikrocontroller. Aus gewohnheit kommt wieder ein AVR ATmega8 zum Einsatz. Zur bequemen Auswertung habe ich dieses mal den ICP (Input Compare Pin) bemüht. Da ich bis jetzt keine größere Erfahrung mit dem Komparator hatte, inspirierte ich mich ein wenig an der Atmel AppNote [http://www.atmel.com/Images/doc8014.pdf AVR135]. Diese beschreibt die Auswertung des Duty-Cylces eines PWM-Signals, also genau das, was man für den Empfänger braucht.= Um einen ungefähren Ausgangswert zu haben, eine kleine Rechnung: das kürzeste Signal hat eine Pulsweite von etwa 2ms, das längste 9ms. Diese müssen also zuverlässig erkannt werden. Der AVR läuft mit 12MHz (der Quarz steckt noch vom [[EMR7370]] im Breadboard), wodurch der AVR eine Zyklusdauer von 83,33ns entspricht. 8ms enstprechen genau 96000 Taktzyklen - etwas viel für den 16-Bit-Timer. Mit dem großzügigen Vorteiler 1024 kommt man auf knapp 94. Bleib noch die Frage, ob die 2 und 4ms sauber unterschieden werden können. 2ms entspricht 23 Timerzyklen, 4ms 47 - also durchaus brauchbare Werte. Zur Bestätigung dieser Theorie baute ich die AppNote so um, dass sie mir die Zählerstände für die jeweiligen High-Zyklen ausgab - mit durchschlagendem Erfolg. Zwar wackelten die Werte ein wenig, das aber im mehr als vertretbaren Rahmen. Zur Auswertung wird eine kleine Statemachine verwendet, was sich schlimmer anhört, als es eigentlich ist. In einer Variable wird der Zustand des Empfangs geschrieben: Warten auf Paket, Synchronisiert + Datenempfang, Fertig. Wird ein Paket empfangen, werden die Bits in ein Array geschrieben und ein Zähler hochgezählt. Ist dieser bei 36 (der Anzahl der Bits) angelangt, geht der Empfänger in den Zustand Fertig über und keine weiteren Bits werden eingelesen. Ist die Auswertung abgeschlossen, geht der Zustand in "Warten" zurück. Wird eine Pulslänge empfangen, die weder einer 1, 0 noch Sync entspricht, wird der Automat ebenfalls in Warten zurückgesetzt, wodurch die zuletzt empfangenen Bits verworfen werden. ==Der Trick mit den Bits== Zunächst habe ich Bits einfach wie sie gekommen sind in den Array geschrieben und erst zur Auswertung in die richtige Reihenfolge gebracht. Das kostet Zeit und Speicher, was sich durch geschickten Code minimieren lässt. Schaut man sich das Nibble-weise Bitreversal genauer an, {| class="wikitable" |- ! Bit mit Nr. !! (Binär) !! soll in Spalte !! (Binär) |- | 0 || 0000 || 4 || 0100 |- | 1 || 0001 || 5 || 0101 |- | 2 || 0010 || 6 || 0110 |- | 3 || 0011 || 7 || 0111 |- | 4 || 0100 || 0 || 0000 |- | 5 || 0101 || 1 || 0001 |- | 6 || 0110 || 2 || 0010 |- | 7 || 0111 || 3 || 0011 |} sieht man, dass man für die Zuordnung eigentlich nur Bit 3 kippen muss. Alle Bits ab Bit 4 kann man für die Zuordnung der Bytes verwenden, was im Quellcode wie folgt aussieht: <source lang="c"> if(bit == TCM_BIT_1) { uint8_t bytepos = tcm_pos >> 3; uint8_t bitpos = (tcm_pos ^ 4) & 7; tcm_bits[bytepos] |= 1<<bitpos; } </source> Das spart wenn ich mich recht erinnere knapp 40 Byte und wahrscheinlich einige Zyklen in der CPU. 9be11a558edd29b975af67297f9915870f59375b Datei:TCM vorne.jpg 6 300 752 2012-05-02T20:30:03Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:TCM innen.jpg 6 301 753 2012-05-02T20:31:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:TCM sender.jpg 6 302 754 2012-05-02T20:31:35Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Raspberry io.jpg 6 303 758 2012-05-05T15:08:43Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Raspberry Pi IO 0 304 759 2012-05-05T15:37:56Z Chris 2 Seite angelegt wikitext text/x-wiki [[Datei:Raspberry io.jpg|200px|thumb|Raspberry Pi mit angeschlossenen LEDs]] Ich war einer der glücklichen, die einen der [http://hobbyelektronik.org/b/2012/04/er-ist-d/ ersten] [http://www.raspberrypi.org/ Raspberry Pi]s ergattern konnte. Zu meiner Schande muss ich gestehen, dass ich relativ lange gezögert habe, mich intensiver mit dem Computerchen zu beschäftigen. Interessant für Bastler ist auf jeden Fall die anschließbare Peripherie. Neben UART, SPI und I²C (für letztere existieren noch keine Treiber und ich bin leider noch zu blöd welche zu schreiben) existieren auch frei belegbare [http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 GPIOs] auf dem Board. =Erster Test= Das [http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29 Beispielprogramm] erfüllt seinen Zweck sehr gut. Nach ein wenig Herumspielen wollte ich wissen, wie schnell man denn die Bits wackeln lassen kann. Eine kleinere Änderung im Source lässt GPIO17 (bzw. "GPIO 0" an der Steckerbelegung - ich möchte nicht wissen, wer auf diese missverständliche Namensgebung gekommen ist) mit nahezu maximaler Frequenz 1000 ein- und ausschalten. <source lang="c"> for (rep=0; rep<1000; rep++) { GPIO_SET = 1<<17; GPIO_CLR = 1<<17; } </source> Mit den Shellbefehlen <pre> gcc io.c sudo ./a.out </pre> Lässt sich der Code kompilieren und anschließend ausführen. Der Logic-Analyzer misst bei dem Progrämmchen knapp 13MHz, wobei ab und zu geringfügig größere Pausen entstehen, die die Frequenz auf 11MHz absinken lassen. Das ist ordentlich! =Das Problem mit root= Das Beispielprogramm funktioniert also super, solange man es als root ausführt. Hinsichtlich der Sicherheit ist das jedoch etwas ungeschickt - wer möchte seine Programme dauerhaft als root ausführen? Besonders für mein Vorhaben eine ganz schlechte Idee: ich möchte als kleine Demonstration LEDs per Browser schalten lassen. Gleichzeitig verbietet der gesunde Menschenverstand, einen Webserver oder gar PHP als root-User laufen zu lassen (besonders in Hinblick auf die [http://heise.de/-1567906 schlechte] [http://heise.de/-1567433 Presse] in den letzten Tagen). Auch das /dev/mem-Interface möchte man nicht unbedingt fürs Userland freigeben (was zudem auch nicht funktioniert). Glücklicherweise kann man auf die GPIOs einzeln über virtuelle Dateien zugreifen. Das ist zwar nicht ganz so schnell, dafür kann man die virtuellen Dateien "normalen" Benutzern zugänglich machen. Dieses Zugänglichmachen findet für jeden Pin in 4 Schritten statt (hier am Beispiel von GPIO17): <pre> sudo echo "17" > /sys/class/gpio/export sudo echo "out" > /sys/class/gpio/gpio17/direction sudo chmod 555 /sys/class/gpio/gpio17/value sudo chmod 555 /sys/class/gpio/gpio17/direction </pre> Die letzten beiden Zeilen erlauben Lese- und Schreibzugriff für Besitzer (root), Gruppe (root) und jeden anderen. Alternativ kann man auch mit chown den Besitzer bzw. die Gruppe ändern, sodass man keinen Zugriff für jeden geben muss. In meinem Fall ist es aber (noch) egal. Um alle Ports auf einmal "freizugeben" habe ich eine kleines Shell-Script geschrieben, die dies erledigt: <pre> #!/bin/sh echo "17" > /sys/class/gpio/export echo "18" > /sys/class/gpio/export echo "21" > /sys/class/gpio/export echo "22" > /sys/class/gpio/export echo "23" > /sys/class/gpio/export echo "24" > /sys/class/gpio/export echo "25" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction echo "out" > /sys/class/gpio/gpio18/direction echo "out" > /sys/class/gpio/gpio21/direction echo "out" > /sys/class/gpio/gpio22/direction echo "out" > /sys/class/gpio/gpio23/direction echo "out" > /sys/class/gpio/gpio24/direction echo "out" > /sys/class/gpio/gpio25/direction chmod 555 /sys/class/gpio/gpio17/value chmod 555 /sys/class/gpio/gpio18/value chmod 555 /sys/class/gpio/gpio21/value chmod 555 /sys/class/gpio/gpio22/value chmod 555 /sys/class/gpio/gpio23/value chmod 555 /sys/class/gpio/gpio24/value chmod 555 /sys/class/gpio/gpio25/value chmod 555 /sys/class/gpio/gpio17/direction chmod 555 /sys/class/gpio/gpio18/direction chmod 555 /sys/class/gpio/gpio21/direction chmod 555 /sys/class/gpio/gpio22/direction chmod 555 /sys/class/gpio/gpio23/direction chmod 555 /sys/class/gpio/gpio24/direction chmod 555 /sys/class/gpio/gpio25/direction </pre> Für alle, die Linux nicht kennen: das "#!/bin/sh" am Anfang ist kein gewöhnlicher Kommentar, sondern ein [[wpde:Shebang|Shebang]], das der Bash (also der Konsole) sagt, mit was die Datei ausgeführt werden möchte. Wichtig ist auch, dass die Zeilenenden auf Linefeed (\n) und nicht auf Carrier Return+Linefeed eingestellt sind. Jeder gute Editor (z. B. Nodepad++ oder SciTE) kann das. Wichtig ist anschließend, dass die Datei vor dem Start Ausführungsrechte bekommt: <pre> chmod 770 gpio.sh </pre> Anschließend kann man sie mit dem Befehl folgendem Befehl ausführen: <pre> sudo ./gpio </pre> =Webserver= Ein grundlegendes Element fehlt noch: der Webserver, was wahrscheinlich am einfachsten mit [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] geht. Hier die Befehle, die ich zur Installation von [http://www.lighttpd.net/ lighttpd] mit PHP5 verwendet habe (keine Garantie auf Funktionalität, Vollständigkeit und Korrektheit): <pre> sudo groupadd www-data sudo aptitude install lighttpd sudo aptitude install php5-cgi sudo lighty-enable-mod fastcgi sudo adduser pi www-data sudo chown -R www-data:www-data /var/www sudo chmod -R 775 /var/www </pre> Damit PHP funktioniert, muss in der Datei /etc/lighttpd/lighttpd.conf (wenn noch nicht vorhanden) durch das Ausführen von <pre> sudo nano /etc/lighttpd/lighttpd.conf </pre> folgender Text hinzugefügt werden: <pre> fastcgi.server = ( ".php" => (( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket" ))) </pre> Nach einem Server-Neustart mit <pre> sudo /etc/init.d/lighttpd force-reload </pre> sollte der Raspberry Pi per HTTP erreichbar sein. [[Kategorie:PC]] [[Kategorie:Raspberry Pi]] 53a6fe5fdba5f7b84ec0d7f6483b368415244343 760 759 2012-05-05T15:48:23Z Chris 2 wikitext text/x-wiki [[Datei:Raspberry io.jpg|200px|thumb|Raspberry Pi mit angeschlossenen LEDs]] Ich war einer der glücklichen, die einen der [http://hobbyelektronik.org/b/2012/04/er-ist-d/ ersten] [http://www.raspberrypi.org/ Raspberry Pi]s ergattern konnte. Zu meiner Schande muss ich gestehen, dass ich relativ lange gezögert habe, mich intensiver mit dem Computerchen zu beschäftigen. Interessant für Bastler ist auf jeden Fall die anschließbare Peripherie. Neben UART, SPI und I²C (für letztere existieren noch keine Treiber und ich bin leider noch zu blöd welche zu schreiben) existieren auch frei belegbare [http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 GPIOs] auf dem Board. =Erster Test= Das [http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29 Beispielprogramm] erfüllt seinen Zweck sehr gut. Nach ein wenig Herumspielen wollte ich wissen, wie schnell man denn die Bits wackeln lassen kann. Eine kleinere Änderung im Source lässt GPIO17 (bzw. "GPIO 0" an der Steckerbelegung - ich möchte nicht wissen, wer auf diese missverständliche Namensgebung gekommen ist) mit nahezu maximaler Frequenz 1000 ein- und ausschalten. <source lang="c"> for (rep=0; rep<1000; rep++) { GPIO_SET = 1<<17; GPIO_CLR = 1<<17; } </source> Mit den Shellbefehlen <pre> gcc io.c sudo ./a.out </pre> Lässt sich der Code kompilieren und anschließend ausführen. Der Logic-Analyzer misst bei dem Progrämmchen knapp 13MHz, wobei ab und zu geringfügig größere Pausen entstehen, die die Frequenz auf 11MHz absinken lassen. Das ist ordentlich! =Das Problem mit root= Das Beispielprogramm funktioniert also super, solange man es als root ausführt. Hinsichtlich der Sicherheit ist das jedoch etwas ungeschickt - wer möchte seine Programme dauerhaft als root ausführen? Besonders für mein Vorhaben eine ganz schlechte Idee: ich möchte als kleine Demonstration LEDs per Browser schalten lassen. Gleichzeitig verbietet der gesunde Menschenverstand, einen Webserver oder gar PHP als root-User laufen zu lassen (besonders in Hinblick auf die [http://heise.de/-1567906 schlechte] [http://heise.de/-1567433 Presse] in den letzten Tagen). Auch das /dev/mem-Interface möchte man nicht unbedingt fürs Userland freigeben (was zudem auch nicht funktioniert). Glücklicherweise kann man auf die GPIOs einzeln über virtuelle Dateien zugreifen. Das ist zwar nicht ganz so schnell, dafür kann man die virtuellen Dateien "normalen" Benutzern zugänglich machen. Dieses Zugänglichmachen findet für jeden Pin in 4 Schritten statt (hier am Beispiel von GPIO17): <pre> sudo echo "17" > /sys/class/gpio/export sudo echo "out" > /sys/class/gpio/gpio17/direction sudo chmod 555 /sys/class/gpio/gpio17/value sudo chmod 555 /sys/class/gpio/gpio17/direction </pre> Die letzten beiden Zeilen erlauben Lese- und Schreibzugriff für Besitzer (root), Gruppe (root) und jeden anderen. Alternativ kann man auch mit chown den Besitzer bzw. die Gruppe ändern, sodass man keinen Zugriff für jeden geben muss. In meinem Fall ist es aber (noch) egal. Um alle Ports auf einmal "freizugeben" habe ich eine kleines Shell-Script geschrieben, die dies erledigt: <pre> #!/bin/sh echo "17" > /sys/class/gpio/export echo "18" > /sys/class/gpio/export echo "21" > /sys/class/gpio/export echo "22" > /sys/class/gpio/export echo "23" > /sys/class/gpio/export echo "24" > /sys/class/gpio/export echo "25" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction echo "out" > /sys/class/gpio/gpio18/direction echo "out" > /sys/class/gpio/gpio21/direction echo "out" > /sys/class/gpio/gpio22/direction echo "out" > /sys/class/gpio/gpio23/direction echo "out" > /sys/class/gpio/gpio24/direction echo "out" > /sys/class/gpio/gpio25/direction chmod 555 /sys/class/gpio/gpio17/value chmod 555 /sys/class/gpio/gpio18/value chmod 555 /sys/class/gpio/gpio21/value chmod 555 /sys/class/gpio/gpio22/value chmod 555 /sys/class/gpio/gpio23/value chmod 555 /sys/class/gpio/gpio24/value chmod 555 /sys/class/gpio/gpio25/value chmod 555 /sys/class/gpio/gpio17/direction chmod 555 /sys/class/gpio/gpio18/direction chmod 555 /sys/class/gpio/gpio21/direction chmod 555 /sys/class/gpio/gpio22/direction chmod 555 /sys/class/gpio/gpio23/direction chmod 555 /sys/class/gpio/gpio24/direction chmod 555 /sys/class/gpio/gpio25/direction </pre> Für alle, die Linux nicht kennen: das "#!/bin/sh" am Anfang ist kein gewöhnlicher Kommentar, sondern ein [[wpde:Shebang|Shebang]], das der Bash (also der Konsole) sagt, mit was die Datei ausgeführt werden möchte. Wichtig ist auch, dass die Zeilenenden auf Linefeed (\n) und nicht auf Carrier Return+Linefeed eingestellt sind. Jeder gute Editor (z. B. Nodepad++ oder SciTE) kann das. Wichtig ist anschließend, dass die Datei vor dem Start Ausführungsrechte bekommt: <pre> chmod 770 gpio.sh </pre> Anschließend kann man sie mit dem Befehl folgendem Befehl ausführen: <pre> sudo ./gpio </pre> '''Achtung''': Die Freigabe der GPIOs ist nicht persistent. Nach einem Neustart muss das Script erneut ausgeführt werden! =Webserver= Ein grundlegendes Element fehlt noch: der Webserver, was wahrscheinlich am einfachsten mit [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] geht. Hier die Befehle, die ich zur Installation von [http://www.lighttpd.net/ lighttpd] mit PHP5 verwendet habe (keine Garantie auf Funktionalität, Vollständigkeit und Korrektheit): <pre> sudo groupadd www-data sudo aptitude install lighttpd sudo aptitude install php5-cgi sudo lighty-enable-mod fastcgi sudo adduser pi www-data sudo chown -R www-data:www-data /var/www sudo chmod -R 775 /var/www </pre> Damit PHP funktioniert, muss in der Datei /etc/lighttpd/lighttpd.conf (wenn noch nicht vorhanden) durch das Ausführen von <pre> sudo nano /etc/lighttpd/lighttpd.conf </pre> folgender Text hinzugefügt werden: <pre> fastcgi.server = ( ".php" => (( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket" ))) </pre> Nach einem Server-Neustart mit <pre> sudo /etc/init.d/lighttpd force-reload </pre> sollte der Raspberry Pi per HTTP erreichbar sein. =Software= ==Server== Wie schon erwähnt läuft auf dem Server (oder sollte zumindest) PHP laufen. Da ich es nicht mag, Seiten wegen Kleinigkeiten neu zu laden, kommt ein [[wpde:Ajax (Programmierung)|Ajax]]/[http://json.org/ JSON]-Interface zum Einsatz. Dementsprechend fällt die Serversoftware minimalistisch aus. Beispielsweise übernimmt read.php das Lesen der Ports. Die Informationen werden in ein assoziatives (Name => Wert) Array geschrieben, ins JSON-Format umgewandelt und an den Client ausgegeben: <source lang="php"> <?php $bits = array(17, 18, 21, 22, 23, 24, 25); $retval = array(); for($x = 0; $x < count($bits); $x++) { $bit = $bits[$x]; $val = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/value")); $dir = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/direction")); $val = $val == "1" ? 1 : 0; $dir = $dir == "out" ? "o" : "i"; $retval[] = array("bit" => $bit, "val" => $val, "dir" => $dir); } echo json_encode($retval); </source> =Download= [[Kategorie:PC]] [[Kategorie:Raspberry Pi]] 33baf705c837944d4ab64b9c0cea53d1ff8f6511 764 760 2012-05-05T16:18:46Z Chris 2 Seite (unter Vorbehalt ;-)) fertiggestellt wikitext text/x-wiki [[Datei:Raspberry io.jpg|200px|thumb|Raspberry Pi mit angeschlossenen LEDs]] Ich war einer der glücklichen, die einen der [http://hobbyelektronik.org/b/2012/04/er-ist-d/ ersten] [http://www.raspberrypi.org/ Raspberry Pi]s ergattern konnte. Zu meiner Schande muss ich gestehen, dass ich relativ lange gezögert habe, mich intensiver mit dem Computerchen zu beschäftigen. Interessant für Bastler ist auf jeden Fall die anschließbare Peripherie. Neben UART, SPI und I²C (für letztere existieren noch keine Treiber und ich bin leider noch zu blöd welche zu schreiben) existieren auch frei belegbare [http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 GPIOs] auf dem Board. =Erster Test= Das [http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29 Beispielprogramm] erfüllt seinen Zweck sehr gut. Nach ein wenig Herumspielen wollte ich wissen, wie schnell man denn die Bits wackeln lassen kann. Eine kleinere Änderung im Source lässt GPIO17 (bzw. "GPIO 0" an der Steckerbelegung - ich möchte nicht wissen, wer auf diese missverständliche Namensgebung gekommen ist) mit nahezu maximaler Frequenz 1000 ein- und ausschalten. <source lang="c"> for (rep=0; rep<1000; rep++) { GPIO_SET = 1<<17; GPIO_CLR = 1<<17; } </source> Mit den Shellbefehlen <pre> gcc io.c sudo ./a.out </pre> Lässt sich der Code kompilieren und anschließend ausführen. Der Logic-Analyzer misst bei dem Progrämmchen knapp 13MHz, wobei ab und zu geringfügig größere Pausen entstehen, die die Frequenz auf 11MHz absinken lassen. Das ist ordentlich! =Das Problem mit root= Das Beispielprogramm funktioniert also super, solange man es als root ausführt. Hinsichtlich der Sicherheit ist das jedoch etwas ungeschickt - wer möchte seine Programme dauerhaft als root ausführen? Besonders für mein Vorhaben eine ganz schlechte Idee: ich möchte als kleine Demonstration LEDs per Browser schalten lassen. Gleichzeitig verbietet der gesunde Menschenverstand, einen Webserver oder gar PHP als root-User laufen zu lassen (besonders in Hinblick auf die [http://heise.de/-1567906 schlechte] [http://heise.de/-1567433 Presse] in den letzten Tagen). Auch das /dev/mem-Interface möchte man nicht unbedingt fürs Userland freigeben (was zudem auch nicht funktioniert). Glücklicherweise kann man auf die GPIOs einzeln über virtuelle Dateien zugreifen. Das ist zwar nicht ganz so schnell, dafür kann man die virtuellen Dateien "normalen" Benutzern zugänglich machen. Dieses Zugänglichmachen findet für jeden Pin in 4 Schritten statt (hier am Beispiel von GPIO17): <pre> sudo echo "17" > /sys/class/gpio/export sudo echo "out" > /sys/class/gpio/gpio17/direction sudo chmod 555 /sys/class/gpio/gpio17/value sudo chmod 555 /sys/class/gpio/gpio17/direction </pre> Die letzten beiden Zeilen erlauben Lese- und Schreibzugriff für Besitzer (root), Gruppe (root) und jeden anderen. Alternativ kann man auch mit chown den Besitzer bzw. die Gruppe ändern, sodass man keinen Zugriff für jeden geben muss. In meinem Fall ist es aber (noch) egal. Um alle Ports auf einmal "freizugeben" habe ich eine kleines Shell-Script geschrieben, die dies erledigt: <pre> #!/bin/sh echo "17" > /sys/class/gpio/export echo "18" > /sys/class/gpio/export echo "21" > /sys/class/gpio/export echo "22" > /sys/class/gpio/export echo "23" > /sys/class/gpio/export echo "24" > /sys/class/gpio/export echo "25" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction echo "out" > /sys/class/gpio/gpio18/direction echo "out" > /sys/class/gpio/gpio21/direction echo "out" > /sys/class/gpio/gpio22/direction echo "out" > /sys/class/gpio/gpio23/direction echo "out" > /sys/class/gpio/gpio24/direction echo "out" > /sys/class/gpio/gpio25/direction chmod 555 /sys/class/gpio/gpio17/value chmod 555 /sys/class/gpio/gpio18/value chmod 555 /sys/class/gpio/gpio21/value chmod 555 /sys/class/gpio/gpio22/value chmod 555 /sys/class/gpio/gpio23/value chmod 555 /sys/class/gpio/gpio24/value chmod 555 /sys/class/gpio/gpio25/value chmod 555 /sys/class/gpio/gpio17/direction chmod 555 /sys/class/gpio/gpio18/direction chmod 555 /sys/class/gpio/gpio21/direction chmod 555 /sys/class/gpio/gpio22/direction chmod 555 /sys/class/gpio/gpio23/direction chmod 555 /sys/class/gpio/gpio24/direction chmod 555 /sys/class/gpio/gpio25/direction </pre> Für alle, die Linux nicht kennen: das "#!/bin/sh" am Anfang ist kein gewöhnlicher Kommentar, sondern ein [[wpde:Shebang|Shebang]], das der Bash (also der Konsole) sagt, mit was die Datei ausgeführt werden möchte. Wichtig ist auch, dass die Zeilenenden auf Linefeed (\n) und nicht auf Carrier Return+Linefeed eingestellt sind. Jeder gute Editor (z. B. Nodepad++ oder SciTE) kann das. Wichtig ist anschließend, dass die Datei vor dem Start Ausführungsrechte bekommt: <pre> chmod 770 gpio.sh </pre> Anschließend kann man sie mit dem Befehl folgendem Befehl ausführen: <pre> sudo ./gpio </pre> '''Achtung''': Die Freigabe der GPIOs ist nicht persistent. Nach einem Neustart muss das Script erneut ausgeführt werden! =Webserver= Ein grundlegendes Element fehlt noch: der Webserver, was wahrscheinlich am einfachsten mit [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] geht. Hier die Befehle, die ich zur Installation von [http://www.lighttpd.net/ lighttpd] mit PHP5 verwendet habe (keine Garantie auf Funktionalität, Vollständigkeit und Korrektheit): <pre> sudo groupadd www-data sudo aptitude install lighttpd sudo aptitude install php5-cgi sudo lighty-enable-mod fastcgi sudo adduser pi www-data sudo chown -R www-data:www-data /var/www sudo chmod -R 775 /var/www </pre> Damit PHP funktioniert, muss in der Datei /etc/lighttpd/lighttpd.conf (wenn noch nicht vorhanden) durch das Ausführen von <pre> sudo nano /etc/lighttpd/lighttpd.conf </pre> folgender Text hinzugefügt werden: <pre> fastcgi.server = ( ".php" => (( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket" ))) </pre> Nach einem Server-Neustart mit <pre> sudo /etc/init.d/lighttpd force-reload </pre> sollte der Raspberry Pi per HTTP erreichbar sein. =Software= ==Server== Wie schon erwähnt läuft auf dem Server (oder sollte zumindest) PHP laufen. Da ich es nicht mag, Seiten wegen Kleinigkeiten neu zu laden, kommt ein [[wpde:Ajax (Programmierung)|Ajax]]/[http://json.org/ JSON]-Interface zum Einsatz. Dementsprechend fällt die Serversoftware minimalistisch aus. Beispielsweise übernimmt read.php das Lesen der Ports und deren Richtung. Die Informationen werden in ein assoziatives (Name => Wert) Array geschrieben, ins JSON-Format umgewandelt und an den Client ausgegeben: <source lang="php"> <?php $bits = array(17, 18, 21, 22, 23, 24, 25); $retval = array(); for($x = 0; $x < count($bits); $x++) { $bit = $bits[$x]; $val = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/value")); $dir = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/direction")); $val = $val == "1" ? 1 : 0; $dir = $dir == "out" ? "o" : "i"; $retval[] = array("bit" => $bit, "val" => $val, "dir" => $dir); } echo json_encode($retval); </source> ==Client== Den Client habe ich relativ schnell (und etwas schlampig) in JavaScript heruntergerissen. Wer etwas JavaScript und die vielen d.ebi, d.ac, d.ce und d.ctn irritiert - das sind Abkürzungen für häufig verwendete Befehle, die ich in common.js definiert habe: <source lang="javascript"> var d = { d : document, w : window, ebi : function(i) { return document.getElementById(i); }, ebn : function(n) { return document.getElementsByName(n); }, febn : function(n) { return document.getElementsByName(n)[0]; }, ce : function(n) { return document.createElement(n); }, ctn : function(n) { return document.createTextNode(n); }, ac : function(p, c) { return p.appendChild(c); }, ac1 : function(p, c) { p.appendChild(c); return p; } } </source> d.ebi steht zum Beispiel für '''d'''ocument.get'''E'''lement'''B'''y'''I'''d d.ac für '''d'''ocument.'''a'''ppend'''C'''hild usw... In diesem Sinne auch eine Entschuldigung an alle, die bei dem Klammer-Massaker einen Knoten im Hirn bekommen ;-) Dadurch, dass nahezu alles in JavaScript gemacht wird, ist der HTML-Body gähnend leer. Erst beim Laden wird der Seite Leben eingehaucht: <gallery> Datei:raspberry_io_gui.png|Benutzerinterface </gallery> Die Richtung und Wert kann man einfach durch Klick auf das jeweilige Element verändern. Durch einen Klick auf "Refresh" kann man die tatsächlichen Werte vom Server ermitteln, nach dem Aktivieren der Checkbox geschieht dies automatisch im Sekundentakt. Getestet wurde die die Anwendung bis jetzt im Firefox, "Standard" Android-Browser und dem aktuellen IE, wobei in letzterem die Aktualisierung nicht richtig funktioniert. <gallery> Datei:Raspberry_io_android.jpg|Raspberry Pi mit Tablet </gallery> =Download= [[Datei:Raspberry Pi IO.zip]] ==Hinweise== Der Inhalt der ZIP-Datei kann relativ einfach mit FileZilla auf den Raspberry (per SSH-Filetransfer) geschoben werden. Der Order IO muss unter /var/www/ liegen, gpio.sh an einem nahezu beliebigen Ort. Vor dem Ausführen der gpio.sh nicht vergessen, die Ausführungsrechte zu setzen! [[Kategorie:PC]] [[Kategorie:Raspberry Pi]] b6c1e3a4fc342a77dab6c1fb2b9449dafa6a11f1 768 764 2012-05-06T08:22:38Z Chris 2 kleine Ergänzungen wikitext text/x-wiki [[Datei:Raspberry io.jpg|200px|thumb|Raspberry Pi mit angeschlossenen LEDs]] Ich war einer der glücklichen, die einen der [http://hobbyelektronik.org/b/2012/04/er-ist-d/ ersten] [http://www.raspberrypi.org/ Raspberry Pi]s ergattern konnte. Zu meiner Schande muss ich gestehen, dass ich relativ lange gezögert habe, mich intensiver mit dem Computerchen zu beschäftigen. Interessant für Bastler ist auf jeden Fall die anschließbare Peripherie. Neben UART, SPI und I²C (für letztere existieren noch keine Treiber und ich bin leider noch zu blöd welche zu schreiben) existieren auch frei belegbare [http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 GPIOs] auf dem Board. =Erster Test= Das [http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29 Beispielprogramm] erfüllt seinen Zweck sehr gut. Nach ein wenig Herumspielen wollte ich wissen, wie schnell man denn die Bits wackeln lassen kann. Eine kleinere Änderung im Source lässt GPIO17 (bzw. "GPIO 0" an der Steckerbelegung - ich möchte nicht wissen, wer auf diese missverständliche Namensgebung gekommen ist) mit nahezu maximaler Frequenz 1000 ein- und ausschalten. <source lang="c"> for (rep=0; rep<1000; rep++) { GPIO_SET = 1<<17; GPIO_CLR = 1<<17; } </source> Mit den Shellbefehlen <pre> gcc io.c sudo ./a.out </pre> Lässt sich der Code kompilieren und anschließend ausführen. Der Logic-Analyzer misst bei dem Progrämmchen knapp 13MHz, wobei ab und zu geringfügig größere Pausen entstehen, die die Frequenz auf 11MHz absinken lassen. Das ist ordentlich! =Das Problem mit root= Das Beispielprogramm funktioniert also super, solange man es als root ausführt. Hinsichtlich der Sicherheit ist das jedoch etwas ungeschickt - wer möchte seine Programme dauerhaft als root ausführen? Besonders für mein Vorhaben eine ganz schlechte Idee: ich möchte als kleine Demonstration LEDs per Browser schalten lassen. Gleichzeitig verbietet der gesunde Menschenverstand, einen Webserver oder gar PHP als root-User laufen zu lassen (besonders in Hinblick auf die [http://heise.de/-1567906 schlechte] [http://heise.de/-1567433 Presse] in den letzten Tagen). Auch das /dev/mem-Interface möchte man nicht unbedingt fürs Userland freigeben (was zudem auch nicht funktioniert). Glücklicherweise kann man auf die GPIOs einzeln über virtuelle Dateien zugreifen. Das ist zwar nicht ganz so schnell, dafür kann man die virtuellen Dateien "normalen" Benutzern zugänglich machen. Dieses Zugänglichmachen findet für jeden Pin in 4 Schritten statt (hier am Beispiel von GPIO17): <pre> sudo echo "17" > /sys/class/gpio/export sudo echo "out" > /sys/class/gpio/gpio17/direction sudo chmod 555 /sys/class/gpio/gpio17/value sudo chmod 555 /sys/class/gpio/gpio17/direction </pre> Die letzten beiden Zeilen erlauben Lese- und Schreibzugriff für Besitzer (root), Gruppe (root) und jeden anderen. Alternativ kann man auch mit chown den Besitzer bzw. die Gruppe ändern, sodass man keinen Zugriff für jeden geben muss. In meinem Fall ist es aber (noch) egal. Um alle Ports auf einmal "freizugeben" habe ich eine kleines Shell-Script geschrieben, die dies erledigt: <pre> #!/bin/sh echo "17" > /sys/class/gpio/export echo "18" > /sys/class/gpio/export echo "21" > /sys/class/gpio/export echo "22" > /sys/class/gpio/export echo "23" > /sys/class/gpio/export echo "24" > /sys/class/gpio/export echo "25" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction echo "out" > /sys/class/gpio/gpio18/direction echo "out" > /sys/class/gpio/gpio21/direction echo "out" > /sys/class/gpio/gpio22/direction echo "out" > /sys/class/gpio/gpio23/direction echo "out" > /sys/class/gpio/gpio24/direction echo "out" > /sys/class/gpio/gpio25/direction chmod 555 /sys/class/gpio/gpio17/value chmod 555 /sys/class/gpio/gpio18/value chmod 555 /sys/class/gpio/gpio21/value chmod 555 /sys/class/gpio/gpio22/value chmod 555 /sys/class/gpio/gpio23/value chmod 555 /sys/class/gpio/gpio24/value chmod 555 /sys/class/gpio/gpio25/value chmod 555 /sys/class/gpio/gpio17/direction chmod 555 /sys/class/gpio/gpio18/direction chmod 555 /sys/class/gpio/gpio21/direction chmod 555 /sys/class/gpio/gpio22/direction chmod 555 /sys/class/gpio/gpio23/direction chmod 555 /sys/class/gpio/gpio24/direction chmod 555 /sys/class/gpio/gpio25/direction </pre> Für alle, die Linux nicht kennen: das "#!/bin/sh" am Anfang ist kein gewöhnlicher Kommentar, sondern ein [[wpde:Shebang|Shebang]], das der Bash (also der Konsole) sagt, mit was die Datei ausgeführt werden möchte. Wichtig ist auch, dass die Zeilenenden auf Linefeed (\n) und nicht auf Carrier Return+Linefeed eingestellt sind. Jeder gute Editor (z. B. Nodepad++ oder SciTE) kann das. Wichtig ist anschließend, dass die Datei vor dem Start Ausführungsrechte bekommt: <pre> chmod 770 gpio.sh </pre> Anschließend kann man sie mit dem Befehl folgendem Befehl ausführen: <pre> sudo ./gpio </pre> '''Achtung''': Die Freigabe der GPIOs ist nicht persistent. Nach einem Neustart muss das Script erneut ausgeführt werden! =Webserver= Ein grundlegendes Element fehlt noch: der Webserver, was wahrscheinlich am einfachsten mit [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] geht. Hier die Befehle, die ich zur Installation von [http://www.lighttpd.net/ lighttpd] mit PHP5 verwendet habe (keine Garantie auf Funktionalität, Vollständigkeit und Korrektheit): <pre> sudo groupadd www-data sudo aptitude install lighttpd sudo aptitude install php5-cgi sudo lighty-enable-mod fastcgi sudo adduser pi www-data sudo chown -R www-data:www-data /var/www sudo chmod -R 775 /var/www </pre> Damit PHP funktioniert, muss in der Datei /etc/lighttpd/lighttpd.conf (wenn noch nicht vorhanden) durch das Ausführen von <pre> sudo nano /etc/lighttpd/lighttpd.conf </pre> folgender Text hinzugefügt werden: <pre> fastcgi.server = ( ".php" => (( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket" ))) </pre> Nach einem Server-Neustart mit <pre> sudo /etc/init.d/lighttpd force-reload </pre> sollte der Raspberry Pi per HTTP erreichbar sein. =Software= ==Server== Wie schon erwähnt läuft auf dem Server (oder sollte zumindest) PHP laufen. Da ich es nicht mag, Seiten wegen Kleinigkeiten neu zu laden, kommt ein [[wpde:Ajax (Programmierung)|Ajax]]/[http://json.org/ JSON]-Interface zum Einsatz. Dementsprechend fällt die Serversoftware minimalistisch aus. Beispielsweise übernimmt read.php das Lesen der Ports und deren Richtung. Die Informationen werden in ein assoziatives (Name => Wert) Array geschrieben, ins JSON-Format umgewandelt und an den Client ausgegeben: <source lang="php"> <?php $bits = array(17, 18, 21, 22, 23, 24, 25); $retval = array(); for($x = 0; $x < count($bits); $x++) { $bit = $bits[$x]; $val = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/value")); $dir = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/direction")); $val = $val == "1" ? 1 : 0; $dir = $dir == "out" ? "o" : "i"; $retval[] = array("bit" => $bit, "val" => $val, "dir" => $dir); } echo json_encode($retval); </source> ==Client== Den Client habe ich relativ schnell (und etwas schlampig) in JavaScript heruntergerissen. Wer etwas JavaScript und die vielen d.ebi, d.ac, d.ce und d.ctn irritiert - das sind Abkürzungen für häufig verwendete Befehle, die ich in common.js definiert habe: <source lang="javascript"> var d = { d : document, w : window, ebi : function(i) { return document.getElementById(i); }, ebn : function(n) { return document.getElementsByName(n); }, febn : function(n) { return document.getElementsByName(n)[0]; }, ce : function(n) { return document.createElement(n); }, ctn : function(n) { return document.createTextNode(n); }, ac : function(p, c) { return p.appendChild(c); }, ac1 : function(p, c) { p.appendChild(c); return p; } } </source> d.ebi steht zum Beispiel für '''d'''ocument.get'''E'''lement'''B'''y'''I'''d d.ac für '''d'''ocument.'''a'''ppend'''C'''hild usw... In diesem Sinne auch eine Entschuldigung an alle, die bei dem Klammer-Massaker einen Knoten im Hirn bekommen ;-) Dadurch, dass nahezu alles in JavaScript gemacht wird, ist der HTML-Body gähnend leer. Erst beim Laden wird der Seite Leben eingehaucht: <gallery> Datei:raspberry_io_gui.png|Benutzerinterface </gallery> Der Code erzeugt zunächst eine Tabelle, die dann durch Objekte von GpioPin gefüllt wird. Durch Klick auf die span-Elemente bzw. Bilder wird der Inhalt umgeschaltet und per XmlHttpRequest ein Kommando an den Server geschickt. Beim Klick auf Lesen wird ebenfalls per XmlHttpRequest eine Anfrage an den Server gesendet, wie oben erwähnt, mit einem JSON-String antwortet. Dies sieht dann z. B. wie folgt aus: <pre> [{"bit":17,"val":0,"dir":"o"},{"bit":18,"val":1,"dir":"o"},{"bit":21,"val":0,"dir":"o"},{"bit":22,"val":0,"dir":"i"},{"bit":23,"val":1,"dir":"i"},{"bit":24,"val":0,"dir":"o"},{"bit":25,"val":0,"dir":"o"}] </pre> Aufgedröselt wird die Struktur deutlicher: <source lang="javascript"> [ { "bit" : 17, "val" : 0, "dir" : "o" },{ "bit" : 18, "val" : 1, "dir" : "o" },{ "bit" : 21, "val" : 0, "dir" : "o" },{ ... } ] </source> Diese wird durch den JSON-parser in ein Objekt umgewandelt, per Schleife zugeordnet und durch die Funktion GpioPin::SetVals() gesetzt. Die Richtung und Wert kann man einfach durch Klick auf das jeweilige Element verändern. Durch einen Klick auf "Refresh" kann man die tatsächlichen Werte vom Server ermitteln, nach dem Aktivieren der Checkbox geschieht dies automatisch im Sekundentakt. Getestet wurde die die Anwendung bis jetzt im Firefox, "Standard" Android-Browser und dem aktuellen IE, wobei in letzterem die Aktualisierung nicht richtig funktioniert. <gallery> Datei:Raspberry_io_android.jpg|Raspberry Pi mit Tablet </gallery> =Download= [[Datei:Raspberry Pi IO.zip]] ==Hinweise== Der Inhalt der ZIP-Datei kann relativ einfach mit FileZilla auf den Raspberry (per SSH-Filetransfer) geschoben werden. Der Order IO muss unter /var/www/ liegen, gpio.sh an einem nahezu beliebigen Ort. Vor dem Ausführen der gpio.sh nicht vergessen, die Ausführungsrechte zu setzen! [[Kategorie:PC]] [[Kategorie:Raspberry Pi]] 666f0533075d164d9142b0de8c6cb1ce59c201f8 769 768 2012-05-06T08:31:49Z Chris 2 /* Erster Test */ wikitext text/x-wiki [[Datei:Raspberry io.jpg|200px|thumb|Raspberry Pi mit angeschlossenen LEDs]] Ich war einer der glücklichen, die einen der [http://hobbyelektronik.org/b/2012/04/er-ist-d/ ersten] [http://www.raspberrypi.org/ Raspberry Pi]s ergattern konnte. Zu meiner Schande muss ich gestehen, dass ich relativ lange gezögert habe, mich intensiver mit dem Computerchen zu beschäftigen. Interessant für Bastler ist auf jeden Fall die anschließbare Peripherie. Neben UART, SPI und I²C (für letztere existieren noch keine Treiber und ich bin leider noch zu blöd welche zu schreiben) existieren auch frei belegbare [http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 GPIOs] auf dem Board. =Erster Test= Das [http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29 Beispielprogramm] erfüllt seinen Zweck sehr gut. Nach ein wenig Herumspielen wollte ich wissen, wie schnell man denn die Bits wackeln lassen kann. Eine kleinere Änderung im Source lässt GPIO17 (bzw. "GPIO 0" an der Steckerbelegung - ich möchte nicht wissen, wer auf diese missverständliche Namensgebung gekommen ist) mit nahezu maximaler Frequenz 1000 ein- und ausschalten. <source lang="c"> for (rep=0; rep<1000; rep++) { GPIO_SET = 1<<17; GPIO_CLR = 1<<17; } </source> Mit den Shellbefehlen <pre> gcc io.c sudo ./a.out </pre> Lässt sich der Code kompilieren und anschließend ausführen. Der Logic-Analyzer misst knapp 77ns Periodendauer, also 13MHz wobei ab und zu geringfügig größere Pausen entstehen, die die Frequenz auf 11MHz absinken lassen. Das ist trotzdem ganz respektabel! =Das Problem mit root= Das Beispielprogramm funktioniert also super, solange man es als root ausführt. Hinsichtlich der Sicherheit ist das jedoch etwas ungeschickt - wer möchte seine Programme dauerhaft als root ausführen? Besonders für mein Vorhaben eine ganz schlechte Idee: ich möchte als kleine Demonstration LEDs per Browser schalten lassen. Gleichzeitig verbietet der gesunde Menschenverstand, einen Webserver oder gar PHP als root-User laufen zu lassen (besonders in Hinblick auf die [http://heise.de/-1567906 schlechte] [http://heise.de/-1567433 Presse] in den letzten Tagen). Auch das /dev/mem-Interface möchte man nicht unbedingt fürs Userland freigeben (was zudem auch nicht funktioniert). Glücklicherweise kann man auf die GPIOs einzeln über virtuelle Dateien zugreifen. Das ist zwar nicht ganz so schnell, dafür kann man die virtuellen Dateien "normalen" Benutzern zugänglich machen. Dieses Zugänglichmachen findet für jeden Pin in 4 Schritten statt (hier am Beispiel von GPIO17): <pre> sudo echo "17" > /sys/class/gpio/export sudo echo "out" > /sys/class/gpio/gpio17/direction sudo chmod 555 /sys/class/gpio/gpio17/value sudo chmod 555 /sys/class/gpio/gpio17/direction </pre> Die letzten beiden Zeilen erlauben Lese- und Schreibzugriff für Besitzer (root), Gruppe (root) und jeden anderen. Alternativ kann man auch mit chown den Besitzer bzw. die Gruppe ändern, sodass man keinen Zugriff für jeden geben muss. In meinem Fall ist es aber (noch) egal. Um alle Ports auf einmal "freizugeben" habe ich eine kleines Shell-Script geschrieben, die dies erledigt: <pre> #!/bin/sh echo "17" > /sys/class/gpio/export echo "18" > /sys/class/gpio/export echo "21" > /sys/class/gpio/export echo "22" > /sys/class/gpio/export echo "23" > /sys/class/gpio/export echo "24" > /sys/class/gpio/export echo "25" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction echo "out" > /sys/class/gpio/gpio18/direction echo "out" > /sys/class/gpio/gpio21/direction echo "out" > /sys/class/gpio/gpio22/direction echo "out" > /sys/class/gpio/gpio23/direction echo "out" > /sys/class/gpio/gpio24/direction echo "out" > /sys/class/gpio/gpio25/direction chmod 555 /sys/class/gpio/gpio17/value chmod 555 /sys/class/gpio/gpio18/value chmod 555 /sys/class/gpio/gpio21/value chmod 555 /sys/class/gpio/gpio22/value chmod 555 /sys/class/gpio/gpio23/value chmod 555 /sys/class/gpio/gpio24/value chmod 555 /sys/class/gpio/gpio25/value chmod 555 /sys/class/gpio/gpio17/direction chmod 555 /sys/class/gpio/gpio18/direction chmod 555 /sys/class/gpio/gpio21/direction chmod 555 /sys/class/gpio/gpio22/direction chmod 555 /sys/class/gpio/gpio23/direction chmod 555 /sys/class/gpio/gpio24/direction chmod 555 /sys/class/gpio/gpio25/direction </pre> Für alle, die Linux nicht kennen: das "#!/bin/sh" am Anfang ist kein gewöhnlicher Kommentar, sondern ein [[wpde:Shebang|Shebang]], das der Bash (also der Konsole) sagt, mit was die Datei ausgeführt werden möchte. Wichtig ist auch, dass die Zeilenenden auf Linefeed (\n) und nicht auf Carrier Return+Linefeed eingestellt sind. Jeder gute Editor (z. B. Nodepad++ oder SciTE) kann das. Wichtig ist anschließend, dass die Datei vor dem Start Ausführungsrechte bekommt: <pre> chmod 770 gpio.sh </pre> Anschließend kann man sie mit dem Befehl folgendem Befehl ausführen: <pre> sudo ./gpio </pre> '''Achtung''': Die Freigabe der GPIOs ist nicht persistent. Nach einem Neustart muss das Script erneut ausgeführt werden! =Webserver= Ein grundlegendes Element fehlt noch: der Webserver, was wahrscheinlich am einfachsten mit [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] geht. Hier die Befehle, die ich zur Installation von [http://www.lighttpd.net/ lighttpd] mit PHP5 verwendet habe (keine Garantie auf Funktionalität, Vollständigkeit und Korrektheit): <pre> sudo groupadd www-data sudo aptitude install lighttpd sudo aptitude install php5-cgi sudo lighty-enable-mod fastcgi sudo adduser pi www-data sudo chown -R www-data:www-data /var/www sudo chmod -R 775 /var/www </pre> Damit PHP funktioniert, muss in der Datei /etc/lighttpd/lighttpd.conf (wenn noch nicht vorhanden) durch das Ausführen von <pre> sudo nano /etc/lighttpd/lighttpd.conf </pre> folgender Text hinzugefügt werden: <pre> fastcgi.server = ( ".php" => (( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket" ))) </pre> Nach einem Server-Neustart mit <pre> sudo /etc/init.d/lighttpd force-reload </pre> sollte der Raspberry Pi per HTTP erreichbar sein. =Software= ==Server== Wie schon erwähnt läuft auf dem Server (oder sollte zumindest) PHP laufen. Da ich es nicht mag, Seiten wegen Kleinigkeiten neu zu laden, kommt ein [[wpde:Ajax (Programmierung)|Ajax]]/[http://json.org/ JSON]-Interface zum Einsatz. Dementsprechend fällt die Serversoftware minimalistisch aus. Beispielsweise übernimmt read.php das Lesen der Ports und deren Richtung. Die Informationen werden in ein assoziatives (Name => Wert) Array geschrieben, ins JSON-Format umgewandelt und an den Client ausgegeben: <source lang="php"> <?php $bits = array(17, 18, 21, 22, 23, 24, 25); $retval = array(); for($x = 0; $x < count($bits); $x++) { $bit = $bits[$x]; $val = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/value")); $dir = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/direction")); $val = $val == "1" ? 1 : 0; $dir = $dir == "out" ? "o" : "i"; $retval[] = array("bit" => $bit, "val" => $val, "dir" => $dir); } echo json_encode($retval); </source> ==Client== Den Client habe ich relativ schnell (und etwas schlampig) in JavaScript heruntergerissen. Wer etwas JavaScript und die vielen d.ebi, d.ac, d.ce und d.ctn irritiert - das sind Abkürzungen für häufig verwendete Befehle, die ich in common.js definiert habe: <source lang="javascript"> var d = { d : document, w : window, ebi : function(i) { return document.getElementById(i); }, ebn : function(n) { return document.getElementsByName(n); }, febn : function(n) { return document.getElementsByName(n)[0]; }, ce : function(n) { return document.createElement(n); }, ctn : function(n) { return document.createTextNode(n); }, ac : function(p, c) { return p.appendChild(c); }, ac1 : function(p, c) { p.appendChild(c); return p; } } </source> d.ebi steht zum Beispiel für '''d'''ocument.get'''E'''lement'''B'''y'''I'''d d.ac für '''d'''ocument.'''a'''ppend'''C'''hild usw... In diesem Sinne auch eine Entschuldigung an alle, die bei dem Klammer-Massaker einen Knoten im Hirn bekommen ;-) Dadurch, dass nahezu alles in JavaScript gemacht wird, ist der HTML-Body gähnend leer. Erst beim Laden wird der Seite Leben eingehaucht: <gallery> Datei:raspberry_io_gui.png|Benutzerinterface </gallery> Der Code erzeugt zunächst eine Tabelle, die dann durch Objekte von GpioPin gefüllt wird. Durch Klick auf die span-Elemente bzw. Bilder wird der Inhalt umgeschaltet und per XmlHttpRequest ein Kommando an den Server geschickt. Beim Klick auf Lesen wird ebenfalls per XmlHttpRequest eine Anfrage an den Server gesendet, wie oben erwähnt, mit einem JSON-String antwortet. Dies sieht dann z. B. wie folgt aus: <pre> [{"bit":17,"val":0,"dir":"o"},{"bit":18,"val":1,"dir":"o"},{"bit":21,"val":0,"dir":"o"},{"bit":22,"val":0,"dir":"i"},{"bit":23,"val":1,"dir":"i"},{"bit":24,"val":0,"dir":"o"},{"bit":25,"val":0,"dir":"o"}] </pre> Aufgedröselt wird die Struktur deutlicher: <source lang="javascript"> [ { "bit" : 17, "val" : 0, "dir" : "o" },{ "bit" : 18, "val" : 1, "dir" : "o" },{ "bit" : 21, "val" : 0, "dir" : "o" },{ ... } ] </source> Diese wird durch den JSON-parser in ein Objekt umgewandelt, per Schleife zugeordnet und durch die Funktion GpioPin::SetVals() gesetzt. Die Richtung und Wert kann man einfach durch Klick auf das jeweilige Element verändern. Durch einen Klick auf "Refresh" kann man die tatsächlichen Werte vom Server ermitteln, nach dem Aktivieren der Checkbox geschieht dies automatisch im Sekundentakt. Getestet wurde die die Anwendung bis jetzt im Firefox, "Standard" Android-Browser und dem aktuellen IE, wobei in letzterem die Aktualisierung nicht richtig funktioniert. <gallery> Datei:Raspberry_io_android.jpg|Raspberry Pi mit Tablet </gallery> =Download= [[Datei:Raspberry Pi IO.zip]] ==Hinweise== Der Inhalt der ZIP-Datei kann relativ einfach mit FileZilla auf den Raspberry (per SSH-Filetransfer) geschoben werden. Der Order IO muss unter /var/www/ liegen, gpio.sh an einem nahezu beliebigen Ort. Vor dem Ausführen der gpio.sh nicht vergessen, die Ausführungsrechte zu setzen! [[Kategorie:PC]] [[Kategorie:Raspberry Pi]] 28cdc4cbb65d0b5d6065098393fe57ef67c0f80e 777 769 2012-06-01T12:01:14Z Chris 2 /* Das Problem mit root */ wikitext text/x-wiki [[Datei:Raspberry io.jpg|200px|thumb|Raspberry Pi mit angeschlossenen LEDs]] Ich war einer der glücklichen, die einen der [http://hobbyelektronik.org/b/2012/04/er-ist-d/ ersten] [http://www.raspberrypi.org/ Raspberry Pi]s ergattern konnte. Zu meiner Schande muss ich gestehen, dass ich relativ lange gezögert habe, mich intensiver mit dem Computerchen zu beschäftigen. Interessant für Bastler ist auf jeden Fall die anschließbare Peripherie. Neben UART, SPI und I²C (für letztere existieren noch keine Treiber und ich bin leider noch zu blöd welche zu schreiben) existieren auch frei belegbare [http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 GPIOs] auf dem Board. =Erster Test= Das [http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29 Beispielprogramm] erfüllt seinen Zweck sehr gut. Nach ein wenig Herumspielen wollte ich wissen, wie schnell man denn die Bits wackeln lassen kann. Eine kleinere Änderung im Source lässt GPIO17 (bzw. "GPIO 0" an der Steckerbelegung - ich möchte nicht wissen, wer auf diese missverständliche Namensgebung gekommen ist) mit nahezu maximaler Frequenz 1000 ein- und ausschalten. <source lang="c"> for (rep=0; rep<1000; rep++) { GPIO_SET = 1<<17; GPIO_CLR = 1<<17; } </source> Mit den Shellbefehlen <pre> gcc io.c sudo ./a.out </pre> Lässt sich der Code kompilieren und anschließend ausführen. Der Logic-Analyzer misst knapp 77ns Periodendauer, also 13MHz wobei ab und zu geringfügig größere Pausen entstehen, die die Frequenz auf 11MHz absinken lassen. Das ist trotzdem ganz respektabel! =Das Problem mit root= Das Beispielprogramm funktioniert also super, solange man es als root ausführt. Hinsichtlich der Sicherheit ist das jedoch etwas ungeschickt - wer möchte seine Programme dauerhaft als root ausführen? Besonders für mein Vorhaben eine ganz schlechte Idee: ich möchte als kleine Demonstration LEDs per Browser schalten lassen. Gleichzeitig verbietet der gesunde Menschenverstand, einen Webserver oder gar PHP als root-User laufen zu lassen (besonders in Hinblick auf die [http://heise.de/-1567906 schlechte] [http://heise.de/-1567433 Presse] in den letzten Tagen). Auch das /dev/mem-Interface möchte man nicht unbedingt fürs Userland freigeben (was zudem auch nicht funktioniert). Glücklicherweise kann man auf die GPIOs einzeln über virtuelle Dateien zugreifen. Das ist zwar nicht ganz so schnell, dafür kann man die virtuellen Dateien "normalen" Benutzern zugänglich machen. Dieses Zugänglichmachen findet für jeden Pin in 4 Schritten statt (hier am Beispiel von GPIO17): <pre> sudo echo "17" > /sys/class/gpio/export sudo echo "out" > /sys/class/gpio/gpio17/direction sudo chmod 555 /sys/class/gpio/gpio17/value sudo chmod 555 /sys/class/gpio/gpio17/direction </pre> Die letzten beiden Zeilen erlauben Lese- und Schreibzugriff für Besitzer (root), Gruppe (root) und jeden anderen. Alternativ kann man auch mit chown den Besitzer bzw. die Gruppe ändern, sodass man keinen Zugriff für jeden geben muss. In meinem Fall ist es aber (noch) egal. Um alle Ports auf einmal "freizugeben" habe ich eine kleines Shell-Script geschrieben, die dies erledigt: <pre> #!/bin/sh echo "17" > /sys/class/gpio/export echo "18" > /sys/class/gpio/export echo "21" > /sys/class/gpio/export echo "22" > /sys/class/gpio/export echo "23" > /sys/class/gpio/export echo "24" > /sys/class/gpio/export echo "25" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction echo "out" > /sys/class/gpio/gpio18/direction echo "out" > /sys/class/gpio/gpio21/direction echo "out" > /sys/class/gpio/gpio22/direction echo "out" > /sys/class/gpio/gpio23/direction echo "out" > /sys/class/gpio/gpio24/direction echo "out" > /sys/class/gpio/gpio25/direction chmod 666 /sys/class/gpio/gpio17/value chmod 666 /sys/class/gpio/gpio18/value chmod 666 /sys/class/gpio/gpio21/value chmod 666 /sys/class/gpio/gpio22/value chmod 666 /sys/class/gpio/gpio23/value chmod 666 /sys/class/gpio/gpio24/value chmod 666 /sys/class/gpio/gpio25/value chmod 666 /sys/class/gpio/gpio17/direction chmod 666 /sys/class/gpio/gpio18/direction chmod 666 /sys/class/gpio/gpio21/direction chmod 666 /sys/class/gpio/gpio22/direction chmod 666 /sys/class/gpio/gpio23/direction chmod 666 /sys/class/gpio/gpio24/direction chmod 666 /sys/class/gpio/gpio25/direction </pre> Für alle, die Linux nicht kennen: das "#!/bin/sh" am Anfang ist kein gewöhnlicher Kommentar, sondern ein [[wpde:Shebang|Shebang]], das der Bash (also der Konsole) sagt, mit was die Datei ausgeführt werden möchte. Wichtig ist auch, dass die Zeilenenden auf Linefeed (\n) und nicht auf Carrier Return+Linefeed eingestellt sind. Jeder gute Editor (z. B. Nodepad++ oder SciTE) kann das. (Noch ein kleiner Hinweis: das 666 ist nichts satanisches, sondern die Berechtigung rw-rw-rw-, die es jedem Benutzer erlaubt, die virtuellen Dateien zu lesen und schreiben. Einen großen Dank an Y.T., der mich auf einen kleinen aber eklatanten Fehler hingewiesen hat) Wichtig ist anschließend, dass die Datei vor dem Start Ausführungsrechte bekommt: <pre> chmod 770 gpio.sh </pre> Anschließend kann man sie mit dem Befehl folgendem Befehl ausführen: <pre> sudo ./gpio </pre> '''Achtung''': Die Freigabe der GPIOs ist nicht persistent. Nach einem Neustart muss das Script erneut ausgeführt werden! =Webserver= Ein grundlegendes Element fehlt noch: der Webserver, was wahrscheinlich am einfachsten mit [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] geht. Hier die Befehle, die ich zur Installation von [http://www.lighttpd.net/ lighttpd] mit PHP5 verwendet habe (keine Garantie auf Funktionalität, Vollständigkeit und Korrektheit): <pre> sudo groupadd www-data sudo aptitude install lighttpd sudo aptitude install php5-cgi sudo lighty-enable-mod fastcgi sudo adduser pi www-data sudo chown -R www-data:www-data /var/www sudo chmod -R 775 /var/www </pre> Damit PHP funktioniert, muss in der Datei /etc/lighttpd/lighttpd.conf (wenn noch nicht vorhanden) durch das Ausführen von <pre> sudo nano /etc/lighttpd/lighttpd.conf </pre> folgender Text hinzugefügt werden: <pre> fastcgi.server = ( ".php" => (( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket" ))) </pre> Nach einem Server-Neustart mit <pre> sudo /etc/init.d/lighttpd force-reload </pre> sollte der Raspberry Pi per HTTP erreichbar sein. =Software= ==Server== Wie schon erwähnt läuft auf dem Server (oder sollte zumindest) PHP laufen. Da ich es nicht mag, Seiten wegen Kleinigkeiten neu zu laden, kommt ein [[wpde:Ajax (Programmierung)|Ajax]]/[http://json.org/ JSON]-Interface zum Einsatz. Dementsprechend fällt die Serversoftware minimalistisch aus. Beispielsweise übernimmt read.php das Lesen der Ports und deren Richtung. Die Informationen werden in ein assoziatives (Name => Wert) Array geschrieben, ins JSON-Format umgewandelt und an den Client ausgegeben: <source lang="php"> <?php $bits = array(17, 18, 21, 22, 23, 24, 25); $retval = array(); for($x = 0; $x < count($bits); $x++) { $bit = $bits[$x]; $val = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/value")); $dir = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/direction")); $val = $val == "1" ? 1 : 0; $dir = $dir == "out" ? "o" : "i"; $retval[] = array("bit" => $bit, "val" => $val, "dir" => $dir); } echo json_encode($retval); </source> ==Client== Den Client habe ich relativ schnell (und etwas schlampig) in JavaScript heruntergerissen. Wer etwas JavaScript und die vielen d.ebi, d.ac, d.ce und d.ctn irritiert - das sind Abkürzungen für häufig verwendete Befehle, die ich in common.js definiert habe: <source lang="javascript"> var d = { d : document, w : window, ebi : function(i) { return document.getElementById(i); }, ebn : function(n) { return document.getElementsByName(n); }, febn : function(n) { return document.getElementsByName(n)[0]; }, ce : function(n) { return document.createElement(n); }, ctn : function(n) { return document.createTextNode(n); }, ac : function(p, c) { return p.appendChild(c); }, ac1 : function(p, c) { p.appendChild(c); return p; } } </source> d.ebi steht zum Beispiel für '''d'''ocument.get'''E'''lement'''B'''y'''I'''d d.ac für '''d'''ocument.'''a'''ppend'''C'''hild usw... In diesem Sinne auch eine Entschuldigung an alle, die bei dem Klammer-Massaker einen Knoten im Hirn bekommen ;-) Dadurch, dass nahezu alles in JavaScript gemacht wird, ist der HTML-Body gähnend leer. Erst beim Laden wird der Seite Leben eingehaucht: <gallery> Datei:raspberry_io_gui.png|Benutzerinterface </gallery> Der Code erzeugt zunächst eine Tabelle, die dann durch Objekte von GpioPin gefüllt wird. Durch Klick auf die span-Elemente bzw. Bilder wird der Inhalt umgeschaltet und per XmlHttpRequest ein Kommando an den Server geschickt. Beim Klick auf Lesen wird ebenfalls per XmlHttpRequest eine Anfrage an den Server gesendet, wie oben erwähnt, mit einem JSON-String antwortet. Dies sieht dann z. B. wie folgt aus: <pre> [{"bit":17,"val":0,"dir":"o"},{"bit":18,"val":1,"dir":"o"},{"bit":21,"val":0,"dir":"o"},{"bit":22,"val":0,"dir":"i"},{"bit":23,"val":1,"dir":"i"},{"bit":24,"val":0,"dir":"o"},{"bit":25,"val":0,"dir":"o"}] </pre> Aufgedröselt wird die Struktur deutlicher: <source lang="javascript"> [ { "bit" : 17, "val" : 0, "dir" : "o" },{ "bit" : 18, "val" : 1, "dir" : "o" },{ "bit" : 21, "val" : 0, "dir" : "o" },{ ... } ] </source> Diese wird durch den JSON-parser in ein Objekt umgewandelt, per Schleife zugeordnet und durch die Funktion GpioPin::SetVals() gesetzt. Die Richtung und Wert kann man einfach durch Klick auf das jeweilige Element verändern. Durch einen Klick auf "Refresh" kann man die tatsächlichen Werte vom Server ermitteln, nach dem Aktivieren der Checkbox geschieht dies automatisch im Sekundentakt. Getestet wurde die die Anwendung bis jetzt im Firefox, "Standard" Android-Browser und dem aktuellen IE, wobei in letzterem die Aktualisierung nicht richtig funktioniert. <gallery> Datei:Raspberry_io_android.jpg|Raspberry Pi mit Tablet </gallery> =Download= [[Datei:Raspberry Pi IO.zip]] ==Hinweise== Der Inhalt der ZIP-Datei kann relativ einfach mit FileZilla auf den Raspberry (per SSH-Filetransfer) geschoben werden. Der Order IO muss unter /var/www/ liegen, gpio.sh an einem nahezu beliebigen Ort. Vor dem Ausführen der gpio.sh nicht vergessen, die Ausführungsrechte zu setzen! [[Kategorie:PC]] [[Kategorie:Raspberry Pi]] 67edc925ab2482258299e3e9191535faf6c00637 779 777 2012-07-24T19:11:03Z Chris 2 was hab ich mir dabei gedacht? wikitext text/x-wiki [[Datei:Raspberry io.jpg|200px|thumb|Raspberry Pi mit angeschlossenen LEDs]] Ich war einer der glücklichen, die einen der [http://hobbyelektronik.org/b/2012/04/er-ist-d/ ersten] [http://www.raspberrypi.org/ Raspberry Pi]s ergattern konnte. Zu meiner Schande muss ich gestehen, dass ich relativ lange gezögert habe, mich intensiver mit dem Computerchen zu beschäftigen. Interessant für Bastler ist auf jeden Fall die anschließbare Peripherie. Neben UART, SPI und I²C (für letztere existieren noch keine Treiber und ich bin leider noch zu blöd welche zu schreiben) existieren auch frei belegbare [http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 GPIOs] auf dem Board. =Erster Test= Das [http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29 Beispielprogramm] erfüllt seinen Zweck sehr gut. Nach ein wenig Herumspielen wollte ich wissen, wie schnell man denn die Bits wackeln lassen kann. Eine kleinere Änderung im Source lässt GPIO17 (bzw. "GPIO 0" an der Steckerbelegung - ich möchte nicht wissen, wer auf diese missverständliche Namensgebung gekommen ist) mit nahezu maximaler Frequenz 1000 ein- und ausschalten. <source lang="c"> for (rep=0; rep<1000; rep++) { GPIO_SET = 1<<17; GPIO_CLR = 1<<17; } </source> Mit den Shellbefehlen <pre> gcc io.c sudo ./a.out </pre> Lässt sich der Code kompilieren und anschließend ausführen. Der Logic-Analyzer misst knapp 77ns Periodendauer, also 13MHz wobei ab und zu geringfügig größere Pausen entstehen, die die Frequenz auf 11MHz absinken lassen. Das ist trotzdem ganz respektabel! =Das Problem mit root= Das Beispielprogramm funktioniert also super, solange man es als root ausführt. Hinsichtlich der Sicherheit ist das jedoch etwas ungeschickt - wer möchte seine Programme dauerhaft als root ausführen? Besonders für mein Vorhaben eine ganz schlechte Idee: ich möchte als kleine Demonstration LEDs per Browser schalten lassen. Gleichzeitig verbietet der gesunde Menschenverstand, einen Webserver oder gar PHP als root-User laufen zu lassen (besonders in Hinblick auf die [http://heise.de/-1567906 schlechte] [http://heise.de/-1567433 Presse] in den letzten Tagen). Auch das /dev/mem-Interface möchte man nicht unbedingt fürs Userland freigeben (was zudem auch nicht funktioniert). Glücklicherweise kann man auf die GPIOs einzeln über virtuelle Dateien zugreifen. Das ist zwar nicht ganz so schnell, dafür kann man die virtuellen Dateien "normalen" Benutzern zugänglich machen. Dieses Zugänglichmachen findet für jeden Pin in 4 Schritten statt (hier am Beispiel von GPIO17): <pre> sudo echo "17" > /sys/class/gpio/export sudo echo "out" > /sys/class/gpio/gpio17/direction sudo chmod 555 /sys/class/gpio/gpio17/value sudo chmod 555 /sys/class/gpio/gpio17/direction </pre> Die letzten beiden Zeilen erlauben Lese- und Schreibzugriff für Besitzer (root), Gruppe (root) und jeden anderen. Alternativ kann man auch mit chown den Besitzer bzw. die Gruppe ändern, sodass man keinen Zugriff für jeden geben muss. In meinem Fall ist es aber (noch) egal. Um alle Ports auf einmal "freizugeben" habe ich eine kleines Shell-Script geschrieben, die dies erledigt: <pre> #!/bin/sh echo "17" > /sys/class/gpio/export echo "18" > /sys/class/gpio/export echo "21" > /sys/class/gpio/export echo "22" > /sys/class/gpio/export echo "23" > /sys/class/gpio/export echo "24" > /sys/class/gpio/export echo "25" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction echo "out" > /sys/class/gpio/gpio18/direction echo "out" > /sys/class/gpio/gpio21/direction echo "out" > /sys/class/gpio/gpio22/direction echo "out" > /sys/class/gpio/gpio23/direction echo "out" > /sys/class/gpio/gpio24/direction echo "out" > /sys/class/gpio/gpio25/direction chmod 666 /sys/class/gpio/gpio17/value chmod 666 /sys/class/gpio/gpio18/value chmod 666 /sys/class/gpio/gpio21/value chmod 666 /sys/class/gpio/gpio22/value chmod 666 /sys/class/gpio/gpio23/value chmod 666 /sys/class/gpio/gpio24/value chmod 666 /sys/class/gpio/gpio25/value chmod 666 /sys/class/gpio/gpio17/direction chmod 666 /sys/class/gpio/gpio18/direction chmod 666 /sys/class/gpio/gpio21/direction chmod 666 /sys/class/gpio/gpio22/direction chmod 666 /sys/class/gpio/gpio23/direction chmod 666 /sys/class/gpio/gpio24/direction chmod 666 /sys/class/gpio/gpio25/direction </pre> Für alle, die Linux nicht kennen: das "#!/bin/sh" am Anfang ist kein gewöhnlicher Kommentar, sondern ein [[wpde:Shebang|Shebang]], das der Bash (also der Konsole) sagt, mit was die Datei ausgeführt werden möchte. Wichtig ist auch, dass die Zeilenenden auf Linefeed (\n) und nicht auf Carrier Return+Linefeed eingestellt sind. Jeder gute Editor (z. B. Nodepad++ oder SciTE) kann das. (Noch ein kleiner Hinweis: das 666 ist nichts satanisches, sondern die Berechtigung rw-rw-rw-, die es jedem Benutzer erlaubt, die virtuellen Dateien zu lesen und schreiben. Einen großen Dank an Y.T., der mich auf einen kleinen aber eklatanten Fehler hingewiesen hat) Wichtig ist anschließend, dass die Datei vor dem Start Ausführungsrechte bekommt: <pre> chmod 770 gpio.sh </pre> Anschließend kann man sie mit dem Befehl folgendem Befehl ausführen: <pre> sudo ./gpio </pre> '''Achtung''': Die Freigabe der GPIOs ist nicht persistent. Nach einem Neustart muss das Script erneut ausgeführt werden! =Webserver= Ein grundlegendes Element fehlt noch: der Webserver, den man wahrscheinlich am einfachsten mit [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] installiert. Hier die Befehle, die ich zur Installation von [http://www.lighttpd.net/ lighttpd] mit PHP5 verwendet habe (keine Garantie auf Funktionalität, Vollständigkeit und Korrektheit): <pre> sudo groupadd www-data sudo aptitude install lighttpd sudo aptitude install php5-cgi sudo lighty-enable-mod fastcgi sudo adduser pi www-data sudo chown -R www-data:www-data /var/www sudo chmod -R 775 /var/www </pre> Damit PHP funktioniert, muss in der Datei /etc/lighttpd/lighttpd.conf (wenn noch nicht vorhanden) durch das Ausführen von <pre> sudo nano /etc/lighttpd/lighttpd.conf </pre> folgender Text hinzugefügt werden: <pre> fastcgi.server = ( ".php" => (( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket" ))) </pre> Nach einem Server-Neustart mit <pre> sudo /etc/init.d/lighttpd force-reload </pre> sollte der Raspberry Pi per HTTP erreichbar sein. =Software= ==Server== Wie schon erwähnt läuft auf dem Server (oder sollte zumindest) PHP laufen. Da ich es nicht mag, Seiten wegen Kleinigkeiten neu zu laden, kommt ein [[wpde:Ajax (Programmierung)|Ajax]]/[http://json.org/ JSON]-Interface zum Einsatz. Dementsprechend fällt die Serversoftware minimalistisch aus. Beispielsweise übernimmt read.php das Lesen der Ports und deren Richtung. Die Informationen werden in ein assoziatives (Name => Wert) Array geschrieben, ins JSON-Format umgewandelt und an den Client ausgegeben: <source lang="php"> <?php $bits = array(17, 18, 21, 22, 23, 24, 25); $retval = array(); for($x = 0; $x < count($bits); $x++) { $bit = $bits[$x]; $val = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/value")); $dir = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/direction")); $val = $val == "1" ? 1 : 0; $dir = $dir == "out" ? "o" : "i"; $retval[] = array("bit" => $bit, "val" => $val, "dir" => $dir); } echo json_encode($retval); </source> ==Client== Den Client habe ich relativ schnell (und etwas schlampig) in JavaScript heruntergerissen. Wer etwas JavaScript und die vielen d.ebi, d.ac, d.ce und d.ctn irritiert - das sind Abkürzungen für häufig verwendete Befehle, die ich in common.js definiert habe: <source lang="javascript"> var d = { d : document, w : window, ebi : function(i) { return document.getElementById(i); }, ebn : function(n) { return document.getElementsByName(n); }, febn : function(n) { return document.getElementsByName(n)[0]; }, ce : function(n) { return document.createElement(n); }, ctn : function(n) { return document.createTextNode(n); }, ac : function(p, c) { return p.appendChild(c); }, ac1 : function(p, c) { p.appendChild(c); return p; } } </source> d.ebi steht zum Beispiel für '''d'''ocument.get'''E'''lement'''B'''y'''I'''d d.ac für '''d'''ocument.'''a'''ppend'''C'''hild usw... In diesem Sinne auch eine Entschuldigung an alle, die bei dem Klammer-Massaker einen Knoten im Hirn bekommen ;-) Dadurch, dass nahezu alles in JavaScript gemacht wird, ist der HTML-Body gähnend leer. Erst beim Laden wird der Seite Leben eingehaucht: <gallery> Datei:raspberry_io_gui.png|Benutzerinterface </gallery> Der Code erzeugt zunächst eine Tabelle, die dann durch Objekte von GpioPin gefüllt wird. Durch Klick auf die span-Elemente bzw. Bilder wird der Inhalt umgeschaltet und per XmlHttpRequest ein Kommando an den Server geschickt. Beim Klick auf Lesen wird ebenfalls per XmlHttpRequest eine Anfrage an den Server gesendet, wie oben erwähnt, mit einem JSON-String antwortet. Dies sieht dann z. B. wie folgt aus: <pre> [{"bit":17,"val":0,"dir":"o"},{"bit":18,"val":1,"dir":"o"},{"bit":21,"val":0,"dir":"o"},{"bit":22,"val":0,"dir":"i"},{"bit":23,"val":1,"dir":"i"},{"bit":24,"val":0,"dir":"o"},{"bit":25,"val":0,"dir":"o"}] </pre> Aufgedröselt wird die Struktur deutlicher: <source lang="javascript"> [ { "bit" : 17, "val" : 0, "dir" : "o" },{ "bit" : 18, "val" : 1, "dir" : "o" },{ "bit" : 21, "val" : 0, "dir" : "o" },{ ... } ] </source> Diese wird durch den JSON-parser in ein Objekt umgewandelt, per Schleife zugeordnet und durch die Funktion GpioPin::SetVals() gesetzt. Die Richtung und Wert kann man einfach durch Klick auf das jeweilige Element verändern. Durch einen Klick auf "Refresh" kann man die tatsächlichen Werte vom Server ermitteln, nach dem Aktivieren der Checkbox geschieht dies automatisch im Sekundentakt. Getestet wurde die die Anwendung bis jetzt im Firefox, "Standard" Android-Browser und dem aktuellen IE, wobei in letzterem die Aktualisierung nicht richtig funktioniert. <gallery> Datei:Raspberry_io_android.jpg|Raspberry Pi mit Tablet </gallery> =Download= [[Datei:Raspberry Pi IO.zip]] ==Hinweise== Der Inhalt der ZIP-Datei kann relativ einfach mit FileZilla auf den Raspberry (per SSH-Filetransfer) geschoben werden. Der Order IO muss unter /var/www/ liegen, gpio.sh an einem nahezu beliebigen Ort. Vor dem Ausführen der gpio.sh nicht vergessen, die Ausführungsrechte zu setzen! [[Kategorie:PC]] [[Kategorie:Raspberry Pi]] be2d9b255866a0f627c7168cdfb260d8100447f2 Datei:Raspberry io gui.png 6 305 761 2012-05-05T15:57:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 765 761 2012-05-05T16:32:25Z Chris 2 lud eine neue Version von „[[Datei:Raspberry io gui.png]]“ hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Raspberry io android.jpg 6 306 762 2012-05-05T16:14:37Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Raspberry Pi IO.zip 6 307 763 2012-05-05T16:16:05Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 767 763 2012-05-06T08:08:50Z Chris 2 lud eine neue Version von „[[Datei:Raspberry Pi IO.zip]]“ hoch: Kommentare hinzugefügt wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 778 767 2012-06-01T12:03:50Z Chris 2 lud eine neue Version von „[[Datei:Raspberry Pi IO.zip]]“ hoch: Saublöden Fehler korrigiert wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Vorlage:Warnung 10 308 775 2012-05-17T08:20:03Z Chris 2 Die Seite wurde neu angelegt: „{{Dokumentation}}<onlyinclude><div style="border:2px solid #ff0000; padding: 10px;"> {{{1|}}} </div> </onlyinclude>“ wikitext text/x-wiki {{Dokumentation}}<onlyinclude><div style="border:2px solid #ff0000; padding: 10px;"> {{{1|}}} </div> </onlyinclude> 679ccd80c9967a9006ac94a0a25148d6e6456748 Vorlage:Warnung/Doku 10 309 776 2012-05-17T08:23:39Z Chris 2 Die Seite wurde neu angelegt: „<pre><nowiki> {{Warnung| }} </nowiki></pre> = Beispiel = <pre><nowiki> {{Warnung|Das ist eine Warnung! }} </nowiki></pre> {{Warnung|Das ist eine Warnung! }}“ wikitext text/x-wiki <pre><nowiki> {{Warnung| }} </nowiki></pre> = Beispiel = <pre><nowiki> {{Warnung|Das ist eine Warnung! }} </nowiki></pre> {{Warnung|Das ist eine Warnung! }} a2d82ee7bc880401e70f8d537e884dc1b2786da5 MediaWiki:Sidebar 8 8 780 620 2012-07-30T20:23:21Z Qsysopr 1 Blog wikitext text/x-wiki * navigation ** mainpage|mainpage ** [http://hobbyelektronik.org/b/ Blog] ** recentchanges-url|recentchanges ** randompage-url|randompage ** Spezial:Alle_Seiten|Alle Seiten * Bereiche ** Category:Elektronik|Elektronik (ohne µC) ** Category:AVR|AVR ** Category:PC|am PC ** Category:Software|Software (PC) ** Category:LCD|LCDs ** Category:Maschinen|Maschinen ** Category:Sonstiges|Sonstiges ** Category:Murks|Murks 5f0e88835e8be8ec1e15208e73344c1813bb61e3 781 780 2012-07-30T20:24:13Z Qsysopr 1 meh wikitext text/x-wiki * navigation ** mainpage|mainpage ** http://hobbyelektronik.org/b/|Blog ** recentchanges-url|recentchanges ** randompage-url|randompage ** Spezial:Alle_Seiten|Alle Seiten * Bereiche ** Category:Elektronik|Elektronik (ohne µC) ** Category:AVR|AVR ** Category:PC|am PC ** Category:Software|Software (PC) ** Category:LCD|LCDs ** Category:Maschinen|Maschinen ** Category:Sonstiges|Sonstiges ** Category:Murks|Murks d0cb7607460dd25dce9e5dbe59eb0d4b8bb6c87d Image Resizer 0 63 782 547 2012-07-30T20:33:10Z Chris 2 Alternativen hinzugefügt wikitext text/x-wiki =Ausgangssituation= Eine Bekannte mit mäßigen Kenntnissen in Bildbearbeitung möchte in regelmäßigen Zeitabständen Bilder auf ihre Homepage hochladen. =Problem= Die Bilder von der Digitalkamera sind groß und die Internetverbindung langsam. Also müssen sie in zwei Hinsichten verkleinert werden: Bildgröße und Dateigröße. =Lösung= PHP war schon öfter der schnelle (und v.a. dreckige) Weg zum Erfolg. Also habe ich Teile meines schon etwas in die Tage gekommenen [http://hobbyelektronik.org/fotos Foto-Albums] verwertet und ein kleines Script erstellt, das die Arbeit übernimmt. Damit die gute Frau die Bilder nicht auf meinen Webserver hochladen muss um sie dann kleiner wieder zu bekommen (hirnrissig, siehe Problem), soll das ganze auf dem eigenen PC laufen - ohne Webserver. PHP bietet von sich aus ein CLI (Commandline-Interface) an, dafür braucht man allerdings trotzdem alle PHP-bezogenen Dateien. Ungut, weil man etwas falsch machen kann... Dank Bambalam und seinem Compiler/Embedder [http://www.bambalam.se/bamcompile/ Bamcompile] kann man aus PHP-Scripts selbstständig lauffähige EXE-Dateien erstellen - sogar mit Extensions! Also habe ich das Script etwas mehr auf CLI angepasst und mit Bamcompile zur Executable verarbeitet. =Verwendung= Einfach Bilddateien (JPG, GIF, PNG) auf resize.exe ziehen und schon wird verkleinert. Die verkleinerten Bilder werden im gleichen Ordner erstellt und ihnen wird ein "_sm" angehängt, aus IMG_1234.JPG wird also IMG_1234_sm.JPG Achtung: bestehende Dateien mit diesem Namen werden ohne Rückfrage überschrieben Momentan wird die lange Kante des Bildes auf 1600 Pixel verkleinert, das Seitenverhältnis bleibt gleich. Bei JPEG wird standardmäßig eine Qualitätsstufe von 90% verwendet. Beide Werte können in der resize.php ganz oben verändert werden, danach muss sie aber neu kompiliert werden. Ich habe einige Testbilder (ok, 10 Megapixel) um sage und schreibe 90% komprimieren können. =Download= [[Datei:Resizepics.zip]] (350 KB) Nach dem Download muss nur noch die ZIP dekomprimiert werden und einmal compile.bat ausgeführt werden (die EXE liegt aus Platzgründen nicht dabei, <strike>dafür der Compiler</strike>) Den Compiler habe ich auf Wunsch meines Hosters gelöscht, da er anscheinend ähnliche Strukturen wie ein Virus hat. Der Compiler selbst kann unter [http://www.bambalam.se/bamcompile/] heruntergeladen werden. Benutzung selbstverständlich auf eigene Gefahr. =Alternativen= Im Nachhinein bin ich von meiner Lösung nicht mehr wirklich überzeugt. Genau genommen hat mein kleiner Hack mehr Nach- als Vorteile. Unter anderem ist die Qualität und Performance nicht die beste. Gute Erfahrungen habe ich mittlerweile mit folgenden Anwendungen gemacht: * [http://www.getpaint.net/ Paint.NET] * [http://www.rw-designer.com/picture-resize Batch Picutre Resize] Diese Tools verwende ich auch für diese Homepage. [[Category:Software]] 5a5fae6d10792cc1f83064759eed8ceae1351b1b 783 782 2012-07-30T20:54:25Z Chris 2 Typo wikitext text/x-wiki =Ausgangssituation= Eine Bekannte mit mäßigen Kenntnissen in Bildbearbeitung möchte in regelmäßigen Zeitabständen Bilder auf ihre Homepage hochladen. =Problem= Die Bilder von der Digitalkamera sind groß und die Internetverbindung langsam. Also müssen sie in zwei Hinsichten verkleinert werden: Bildgröße und Dateigröße. =Lösung= PHP war schon öfter der schnelle (und v.a. dreckige) Weg zum Erfolg. Also habe ich Teile meines schon etwas in die Tage gekommenen [http://hobbyelektronik.org/fotos Foto-Albums] verwertet und ein kleines Script erstellt, das die Arbeit übernimmt. Damit die gute Frau die Bilder nicht auf meinen Webserver hochladen muss um sie dann kleiner wieder zu bekommen (hirnrissig, siehe Problem), soll das ganze auf dem eigenen PC laufen - ohne Webserver. PHP bietet von sich aus ein CLI (Commandline-Interface) an, dafür braucht man allerdings trotzdem alle PHP-bezogenen Dateien. Ungut, weil man etwas falsch machen kann... Dank Bambalam und seinem Compiler/Embedder [http://www.bambalam.se/bamcompile/ Bamcompile] kann man aus PHP-Scripts selbstständig lauffähige EXE-Dateien erstellen - sogar mit Extensions! Also habe ich das Script etwas mehr auf CLI angepasst und mit Bamcompile zur Executable verarbeitet. =Verwendung= Einfach Bilddateien (JPG, GIF, PNG) auf resize.exe ziehen und schon wird verkleinert. Die verkleinerten Bilder werden im gleichen Ordner erstellt und ihnen wird ein "_sm" angehängt, aus IMG_1234.JPG wird also IMG_1234_sm.JPG Achtung: bestehende Dateien mit diesem Namen werden ohne Rückfrage überschrieben Momentan wird die lange Kante des Bildes auf 1600 Pixel verkleinert, das Seitenverhältnis bleibt gleich. Bei JPEG wird standardmäßig eine Qualitätsstufe von 90% verwendet. Beide Werte können in der resize.php ganz oben verändert werden, danach muss sie aber neu kompiliert werden. Ich habe einige Testbilder (ok, 10 Megapixel) um sage und schreibe 90% komprimieren können. =Download= [[Datei:Resizepics.zip]] (350 KB) Nach dem Download muss nur noch die ZIP dekomprimiert werden und einmal compile.bat ausgeführt werden (die EXE liegt aus Platzgründen nicht dabei, <strike>dafür der Compiler</strike>) Den Compiler habe ich auf Wunsch meines Hosters gelöscht, da er anscheinend ähnliche Strukturen wie ein Virus hat. Der Compiler selbst kann unter [http://www.bambalam.se/bamcompile/] heruntergeladen werden. Benutzung selbstverständlich auf eigene Gefahr. =Alternativen= Im Nachhinein bin ich von meiner Lösung nicht mehr wirklich überzeugt. Genau genommen hat mein kleiner Hack mehr Nach- als Vorteile. Unter anderem ist die Qualität und Performance nicht die beste. Gute Erfahrungen habe ich mittlerweile mit folgenden Anwendungen gemacht: * [http://www.getpaint.net/ Paint.NET] * [http://www.rw-designer.com/picture-resize Batch Picture Resize] Diese Tools verwende ich auch für diese Homepage. [[Category:Software]] 5726906885ee609ffa9031bd7618366eccc087fe Hauptseite 0 1 784 766 2012-07-30T20:59:39Z Chris 2 etwas aufgefrischt wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein [http://hobbyelektronik.org/b/ Blog], das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =Neues= *05.05.2012 [[Raspberry Pi IO]] *12.03.2012 [[EMR7370]] *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] =Updates= *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit 6e45b34019f99d7d3d44e6d11a4c729a8f21c5dd 785 784 2012-07-30T21:17:33Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =Neues= *05.05.2012 [[Raspberry Pi IO]] *12.03.2012 [[EMR7370]] *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] =Updates= *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit bffb5a39ec3ffa7ee6b634802972bd32dd227608 788 785 2012-07-31T20:39:17Z Chris 2 Blog-Plugin hinzugefügt, mal sehen ob jetzt die Erde brennt ;) wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[http://hobbyelektronik.org/b/ Blog]= <latestblogposts> =Neues= *05.05.2012 [[Raspberry Pi IO]] *12.03.2012 [[EMR7370]] *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] =Änderungen= *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit 45344269f175cea17347a634fd7b866c0cc5cb9d 789 788 2012-07-31T20:40:07Z Chris 2 und natürlich brennt sie, wenn man das Tag nicht schließt. wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[http://hobbyelektronik.org/b/ Blog]= <latestblogposts /> =Neues= *05.05.2012 [[Raspberry Pi IO]] *12.03.2012 [[EMR7370]] *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] =Änderungen= *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit bff32b1bacd28e8bb22fd9f4e340dd1d449b3b93 791 789 2012-09-13T16:13:24Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *05.05.2012 [[Raspberry Pi IO]] *12.03.2012 [[EMR7370]] *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] *12.09.2011 [[Gartenbrunnen]] ==Änderungen== *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit 5b802bf1e8854cf8b042b0d9e319bbe14861cde8 817 791 2012-09-26T20:31:33Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *26.09.2012 [[Sony Dimmer]] *05.05.2012 [[Raspberry Pi IO]] *12.03.2012 [[EMR7370]] *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] *13.09.2011 [[Modellbau-Leuchtstofflampe]] ==Änderungen== *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit 3d77b56239b5ff00b57fd44fefbffa0caeb0cc00 821 817 2012-10-11T20:07:20Z Chris 2 EAGLE-Toolbar hinzugefügt wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *11.10.2012 [[EAGLE-Toolbar]] *26.09.2012 [[Sony Dimmer]] *05.05.2012 [[Raspberry Pi IO]] *12.03.2012 [[EMR7370]] *29.12.2011 [[Polizeiauto]] *03.10.2011 [[Audioslave]] ==Änderungen== *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung → Downloads]]: Die Firmware steht jetzt zum Download bereit 1e99c59f3a65e8ec6ec57191c789ca670663f6ef MediaWiki:Sidebar 8 8 786 781 2012-07-30T21:18:20Z Qsysopr 1 das Blog ist fett wikitext text/x-wiki * navigation ** mainpage|mainpage ** '''http://hobbyelektronik.org/b/|Blog''' ** recentchanges-url|recentchanges ** randompage-url|randompage ** Spezial:Alle_Seiten|Alle Seiten * Bereiche ** Category:Elektronik|Elektronik (ohne µC) ** Category:AVR|AVR ** Category:PC|am PC ** Category:Software|Software (PC) ** Category:LCD|LCDs ** Category:Maschinen|Maschinen ** Category:Sonstiges|Sonstiges ** Category:Murks|Murks 08b8b4e02109e4429ac0a74ef7a05597f6525431 787 786 2012-07-30T21:18:40Z Qsysopr 1 (und die wiki ist zu blöd dafür) wikitext text/x-wiki * navigation ** mainpage|mainpage ** http://hobbyelektronik.org/b/|Blog ** recentchanges-url|recentchanges ** randompage-url|randompage ** Spezial:Alle_Seiten|Alle Seiten * Bereiche ** Category:Elektronik|Elektronik (ohne µC) ** Category:AVR|AVR ** Category:PC|am PC ** Category:Software|Software (PC) ** Category:LCD|LCDs ** Category:Maschinen|Maschinen ** Category:Sonstiges|Sonstiges ** Category:Murks|Murks d0cb7607460dd25dce9e5dbe59eb0d4b8bb6c87d AVR-Doper 0 44 790 626 2012-09-10T20:08:19Z Chris 2 Nachtrag zum Diamex ALL-AVR hinzugefügt wikitext text/x-wiki {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = C9 | FuseL = 9F }} Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Die Firmware wurde nicht verändert und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download des optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] =AVR-Doper unter Windows 7= Nachdem Windows XP schon etwas betagt ist und Vista eher ein flop war, steht man früher oder später an dem Punkt, Windows 7 zu verwenden. Zwar lassen sich die Vista-Treiber des AVR-Dopers unter Windows 7 installieren, AVR-Studio kann allerdings keine Verbindung zum Doper herstellen. Die Jungs von recursion.jp haben einen Treiber geschrieben, der sowohl unter Win7 x86 und Win7 x64 funktioniert: [http://www.recursion.jp/avrcdc/lowbulk.html http://www.recursion.jp/avrcdc/lowbulk.html] -> "avrcdc_inf.zip" Es kann sein, dass der Treiber manuell signiert werden muss (was bei meiner x86-Installation nicht erforderlich war). Nähere Informationen dazu (und auch der ursprüngliche Hinweis auf den Treiber) befinden sich im [http://forums.obdev.at/viewtopic.php?f=8&t=3591&p=12721#p12721 Forum von Objective Development] =Patch AVR-Studio= Wer den AVR-Doper direkt in Atmels AVR-Studio als STK500 benutzt, erhält bei jedem Herstellen der Verbindung eine nervige Fehlermeldung bezüglich der Firmware-Version. Ein kleiner Registry-Eintrag unterdrückt die Meldung: Unter HKEY_LOCAL_MACHINE\SOFTWARE\Atmel\AVRTools\STK500 muss VersionMajor auf 0x00000002 (2) und VersionMinor auf 0x00000004 (4) geändert werden. Für die, die den Registrierung-Editor nicht bedienen können oder möchten, gibt es eine passende Reg-Datei: [[Datei:Avr-doper-registry.zip]] Wer sich die Tortur angetan hat und den Doper per virtuellem COM-Port an Vista/Win7 x64 zum laufen gebracht hat, muss die Änderung im Pfad HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Atmel\AVRTools\STK500 vornehmen. Also entweder in der .reg-Datei ändern oder manuell dort hin navigieren und bearbeiten. =Minidoper= [[Datei:Minidoper.png|200px|thumb|Mini-Version von Jan]] Jan Räker hat sich die Mühe gemacht und den Doper nochmal ein gutes Stück verkleinert und mir zur Veröffentlichung (unter [http://creativecommons.org/licenses/by-sa/3.0/ by-sa]) bereitgestellt: [[Datei:Minidoper.zip]] =Nachtrag 9/2012= Wer das Henne-Ei-Problem beim AVR-Doper nicht lösen kann und nicht basteln kann oder will, dem kann ich mittlerweile den DIAMEX ALL-AVR ans Herz legen. Dieser kann neben ISP auch TPI und PDI - und, wie ich leidvoll erfahren musste - im Gegensatz zum AVR Dragon die XMega A3 programmieren. [[Category:AVR]] [[Category:USB]] [[Category:PC]] df4f5ae2220d07c86cfe749ad4cd635cb6d3e418 826 790 2012-12-06T16:11:44Z Chris 2 Ach FAQ... wikitext text/x-wiki {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = C9 | FuseL = 9F }} Als ich auf obdev.at gestoßen bin, fiel mir sofort der dort vorgestellte [http://www.obdev.at/products/avrusb/avrdoper.html AVR-Doper] ins Auge. Mein bis dahin aktueller AVR-Programmer war recht primitiv, ein sehr einfacher Adapter für den Parallel-Port der nur ISP kann. Für den Anfang reichte das, allerdings ist er nicht mit AVR Studio kompatibel und kann kein HVSP sowie weitere nette Features wie der AVR-Doper. für den Anfang wurde nur der ISP-Teil auf dem Steckbrett aufgebaut und siehe da: Es funktionierte auf Anhieb und ich konnte direkt aus AVR Studio als STK-500 meine Mikrocontroller mit Programmen befüllen. Nur eines gefiel mir am AVR-Doper nicht: die Größe. Also EAGLE angeworfen und RIPUP auf alle Signale ausgeführt. Nach einigen Stunden Routen bekam ich die Platine auf 10x7cm (ohne die Verwendung von SMD). [[Benutzer:Robert|Robert]] hat mir freundlicherweise wieder einen "Abzug" auf Epoxy gemacht. <gallery> Bild:AVR-Doper-brd.png|Ansicht aus EAGLE Bild:AVR-Doper-auf.jpg|Die bestückte und gelötete Platine </gallery> Die Firmware wurde nicht verändert und kann direkt auf der [http://www.obdev.at/products/avrusb/avrdoper.html Projektseite] heruntergeladen werden Download des optimierten Boards + gespiegelte PDF [[Bild:AVR-Doper.zip‎]] =AVR-Doper unter Windows 7= Nachdem Windows XP schon etwas betagt ist und Vista eher ein flop war, steht man früher oder später an dem Punkt, Windows 7 zu verwenden. Zwar lassen sich die Vista-Treiber des AVR-Dopers unter Windows 7 installieren, AVR-Studio kann allerdings keine Verbindung zum Doper herstellen. Die Jungs von recursion.jp haben einen Treiber geschrieben, der sowohl unter Win7 x86 und Win7 x64 funktioniert: [http://www.recursion.jp/avrcdc/lowbulk.html http://www.recursion.jp/avrcdc/lowbulk.html] -> "avrcdc_inf.zip" Es kann sein, dass der Treiber manuell signiert werden muss (was bei meiner x86-Installation nicht erforderlich war). Nähere Informationen dazu (und auch der ursprüngliche Hinweis auf den Treiber) befinden sich im [http://forums.obdev.at/viewtopic.php?f=8&t=3591&p=12721#p12721 Forum von Objective Development] =Patch AVR-Studio= Wer den AVR-Doper direkt in Atmels AVR-Studio als STK500 benutzt, erhält bei jedem Herstellen der Verbindung eine nervige Fehlermeldung bezüglich der Firmware-Version. Ein kleiner Registry-Eintrag unterdrückt die Meldung: Unter HKEY_LOCAL_MACHINE\SOFTWARE\Atmel\AVRTools\STK500 muss VersionMajor auf 0x00000002 (2) und VersionMinor auf 0x00000004 (4) geändert werden. Für die, die den Registrierung-Editor nicht bedienen können oder möchten, gibt es eine passende Reg-Datei: [[Datei:Avr-doper-registry.zip]] Wer sich die Tortur angetan hat und den Doper per virtuellem COM-Port an Vista/Win7 x64 zum laufen gebracht hat, muss die Änderung im Pfad HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Atmel\AVRTools\STK500 vornehmen. Also entweder in der .reg-Datei ändern oder manuell dort hin navigieren und bearbeiten. =Minidoper= [[Datei:Minidoper.png|200px|thumb|Mini-Version von Jan]] Jan Räker hat sich die Mühe gemacht und den Doper nochmal ein gutes Stück verkleinert und mir zur Veröffentlichung (unter [http://creativecommons.org/licenses/by-sa/3.0/ by-sa]) bereitgestellt: [[Datei:Minidoper.zip]] =Nachtrag 9/2012= Wer das Henne-Ei-Problem beim AVR-Doper nicht lösen kann und nicht basteln kann oder will, dem kann ich mittlerweile den DIAMEX ALL-AVR ans Herz legen. Dieser kann neben ISP auch TPI und PDI - und, wie ich leidvoll erfahren musste - im Gegensatz zum AVR Dragon die XMega A3 programmieren. =Nachtrag 12/2012= Auf vielfachen (hüstel) Wunsch gibt es nun eine '''[[AVR-Doper/FAQ|FAQ]]''' [[Category:AVR]] [[Category:USB]] [[Category:PC]] 509f106a39ea16fae19758b3395e0ad0cb54bffa Datei:Sony aufbau.jpg 6 310 792 2012-09-26T19:37:52Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony bootloader flash.jpg 6 311 793 2012-09-26T19:37:55Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony bot.jpg 6 312 794 2012-09-26T19:38:00Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony bot leiterbahnen.jpg 6 313 795 2012-09-26T19:38:05Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony bot leiterbahnen.png 6 314 796 2012-09-26T19:38:06Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony cdlw.jpg 6 315 797 2012-09-26T19:38:13Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony fet.jpg 6 316 798 2012-09-26T19:38:15Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony fotodiode.jpg 6 317 799 2012-09-26T19:38:16Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony fotodiode eingebaut.jpg 6 318 800 2012-09-26T19:38:25Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 807 800 2012-09-26T19:45:33Z Chris 2 lud eine neue Version von „[[Datei:Sony fotodiode eingebaut.jpg]]“ hoch wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony front.jpg 6 319 801 2012-09-26T19:38:27Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony intern.jpg 6 320 802 2012-09-26T19:38:33Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony leiterbahnen.png 6 321 803 2012-09-26T19:38:35Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony top.jpg 6 322 804 2012-09-26T19:38:39Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony top leiterbahnen.jpg 6 323 805 2012-09-26T19:38:44Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony top traces.png 6 324 806 2012-09-26T19:38:45Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony lichtloch.jpg 6 325 808 2012-09-26T19:45:54Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 809 808 2012-09-26T19:46:29Z Chris 2 lud eine neue Version von „[[Datei:Sony lichtloch.jpg]]“ hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Sony einbau.jpg 6 326 810 2012-09-26T19:59:19Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Sony bot komplett.jpg 6 327 811 2012-09-26T19:59:39Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Sony Dimmer 0 328 812 2012-09-26T20:01:27Z Chris 2 Seite erstellt, Download folgt noch wikitext text/x-wiki Über die übertrieben helle Hintergrundbeleuchtung in meinem Autoradio und dessen vorübergehenden Lösung habe ich mich ja bereits vor geraumer Zeit im Blog ausgelassen. Dass nichts für die Ewigkeit ist, gilt natürlich auch für viele Kleber. So kam es, dass dessen Wirkung auf den "Verdunkelungsstreifen" nachließ und diese ihren Platz verließen. Resultat: ich werde wieder geblendet. Um eine längerfristige Lösung zu erhalten, entschied ich mich, das Problem selbst und nicht dessen Symptome zu behandeln. Die LEDs sollen nachhaltig abgedunkelt werden - da ich nicht genau weiß, was ich vor mir hab heißt es: Bedienteil abnehmen und genauer unter die Lupe nehmen. =Untersuchung= Ein paar Schrauben und Klipse später liegt die Leiterplatte auf dem Tisch. Um die Schaltung besser analysieren zu können, kommt die Kamera und Bildbearbeitung ins Spiel: Fotos von der Ober- und Unterseite in der Bildbearbeitung möglichst deckungsgleich übereinandergelegt erleichtern die Arbeit ungemein. Auf drei zusätzlichen Ebenen befinden sich nachgezeichneten Leiterbahnen und die Durchkontaktierungen. Zwei weitere beinhalten die interessanten Bauteile auf den jeweiligen Seiten: <gallery> Datei:sony_top.jpg|Oberseite Datei:sony_top_leiterbahnen.jpg|Oberseite mit Leiterbahnen Datei:sony_bot.jpg|Unterseite (gespiegelt) Datei:sony_bot_leiterbahnen.jpg| Unterseite mit Leiterbahnen Datei:sony_leiterbahnen.png|Leiterbahnen & Bauteile hervorgehoben </gallery> Eine kleine Anmerkung zu abnehmbaren Bedienteilen (zumindest bei Sony): Blödsinn. Ok, man sieht nicht, um welches Radio es sich handelt und es ist auf den ersten Blick unbrauchbar, kann man jedoch ein anderes Bedienteil ergattern, bringt man es auf jeden Fall wieder zum Laufen. Zumindest konnte ich bei meinem keinen Cryptochip oder etwas in diese Richtung entdecken. Der Displaycontroller (LC irgendwas) hat auch nichts in dieser Richtung integriert. Wie dem auch sei, zumindest wurde ich bei der Schaltung für die LEDs fündig - hier haben die Damen und Herren bei Sony mitgedacht: die Masse aller Leuchtdioden führt über einen 0-Ohm-Widerstand. Dieser durch einen Schalter ersetzt lässt sich die Beleuchtung sehr rudimentär steuern. ==Mehr Einblicke== Nachdem mir das Suchen nach Versorgungsspannungen nur Anhand des Bedienteils zu blöd wurde beschloss ich, mir den Rest vom Radio anzusehen. An der Front des bedienteillosen Radios befinden sich 4 Schrauben - was ich nicht wusste: nur eine hält die Front. Die restlichen halten den Auswurfmechanismus für das Bedienteil (links) und das Mikrofon für die Freisprecheinrichtung (warum dieses sich ausgerechnet hinter dem Bedienteil befindet, konnte ich bis heute nicht herausfinden). Diese habe ich leider so weit gelöst, dass das Mikrofon wegfiel. Da ich nicht wusste, ob es nicht doch eine Schraube des CD-Laufwerks war, kam zur Sicherheit das gesamte Radio mal an die frische Luft. Der Ausbau ist ganz einfach: Blenden der A-Säule abnehmen, Ablage vorne entfernen, drei Halteschrauben für die Mittelkonsole raus drehen, das CD-Fach öffnen, zwei Blenden abnehmen und dort zwei Schrauben lösen und abschließend unter der Mittelkonsole nochmal zwei Schrauben entfernen. Nun kann die Mittelkonsole herausgenommen werden, bei der zuerst die beiden "Lüftungsschlitze" herausgeklipst werden müssen um an die Schrauben des Radios zu kommen. An diesem müssen dann nur noch 4 weitere Schrauben heraus gedreht werden. Damit man das Modul nun ohne Gewalt raus ziehen zu können, kann man noch zwei weitere Schrauben lösen. Alles ganz einfach. Zumindest bin ich mir sehr sicher, dass das Radio der letzte Gegenstand in meinem Auto ist, der gestohlen wird. Dafür trennen nur noch 3 weitere Schrauben den vollen Blick in das Innenleben der Blechbüchse. Ganz nett ist das CD-Laufwerk, das einfach auf die Hauptplatine gesteckt ist. Ist dieses nicht vorhanden, lässt sich das Radio größtenteils verwenden, allerdings fehlt neben der CD auch die USB-Quelle. Genauer betrachtet ist dies sogar mehr als naheliegend: Genauso wie von CD kann der Player vom USB-Stick aus MP3-, AAC- und WMA-Dateien wiedergeben. So unterschiedlich ist das Zeug also nicht, warum sollte man also doppelten Aufwand betreiben? Interessant am Innenleben ist auch die Bestückung der Quarze: Diese sind nicht (wie sonst üblich) möglichst nah an der Platine, sondern stehen gute 5mm in der Luft. Vermutlich wird dadurch versucht, die mechanische Kopplung (Vibrationen) etwas zu verringern. Schließlich müssen Quarze frei schwingen können. Was ich jedoch nicht ganz verstehe, ist das Mikrofon und das Bluetooth-Modul. Ok, das Radio kommt aus Japan, dementsprechend wurde es wohl für Rechtslenker gebaut. Warum gibt es aber keine europäische Version (Mikro links)? Zumal man die Gussform für die Front so machen könnte, dass man das Mikrofon auf beiden Seiten montieren könnte. Whatever. Beim BT-Modul ist verwunderlich, dass dessen Antenne tatsächlich abgetrennt vom Rest ist. Ob die Antenne nun rechts, links, oben oder unten im Gehäuse ist, dürfte relativ egal sein. Hier wurde eine dünne Koax-Leitung und sogar diese unsäglichen U.FL-Buchsen ("Druckknöpfe") verbaut. Kostenoptimierung sieht anders aus. <gallery> Datei:sony_intern.jpg|Sony BT3700U von innen Datei:sony_cdlw.jpg|CD-Laufwerk von unten </gallery> =Verbesserung= An/Aus kann die Beleuchtung nun schon, aber das kann es natürlich nicht gewesen sein. Wie eingangs beschrieben, es sollte was Vernünftiges werden. Wer mich kennt weiß: ein Mikrocontroller muss her, denn: jedes Popelgerät hat mittlerweile einen Umgebungslichtsensor, so soll es auch mit dem Radio geschehen. ==Lichtsensor== Das größte Problem hierbei ist erst einmal: Was wo unterbringen? Dem Mikrocontroller ist es primär egal, wo er werkelt. Nur die Helligkeit sollte da gemessen werden, wo sie her kommt. Zunächst ist allerdings die Frage, welches Bauteil kann/soll verwendet werden. Im Sortierkasten sieht’s mau aus, Reichelt hat ein paar feine Bauteile, die aber eigentlich alle ein bisschen zu groß sind. Geworden ist es dann ein BPW 16N, der für seine bedrahtete Natur relativ klein ist. Das was wäre zumindest teilweise geklärt, bleibt das "Wo". Leider ist die Frontplatte an fast allen Stellen mit Beschriftung oder Bedienelement versehen, einzig zwischen Display und USB-Port befindet sich eine auch von unten relativ gut zugängliche Stelle. Was hier fehlt ist natürlich die Transparenz. Dafür kann mit Proxxon und Schleifkopf gesorgt werden. Mit niedriger Drehzahl und Fingerspitzengefühl ging es der Plaste an den Kragen. Da ich nur ein Sichtfenster und kein Loch wollte, hieß es immer wieder absetzen und Tiefe kontrollieren. Nach 4 Nachbohrungen war endlich ein Licht am Ende des "Tunnels" zu sehen. An der B-Note (Sauberkeit des Sichtfensters) könnte ich zwar noch ein bisschen arbeiten, für meine Anforderungen genügte die Qualität allerdings: <gallery> Datei:sony_lichtloch.jpg|Gebohrtes Lichtloch Datei:sony_front.jpg|Gebohrtes Lichtloch von oben Datei:sony_fotodiode.jpg|Gelötete Fotodiode Datei:sony_fotodiode_eingebaut.jpg|Fotodiode eingebaut </gallery> ==Ansteuerung== [[Bild:sony_fet.jpg|thumb|Aufgelöteter FET mit Gatewiderstand]] Auf LED-Seite sieht die Sache schon ein wenig anders aus. Da die Elektronik ein paar LEDs ein- und ausschalten kann, würde eine Stromquelle für gegenläufiges Blinken der restlichen Leuchtdioden sorgen. Zudem ist eine Stromquelle vergleichsweise groß und für diesen Zweck etwas übertrieben. Aus diesen Gründen soll Pulsweitenmodulation eingesetzt werden. Zum Schalten kommt der im SOT-23-Gehäuse verfügbare BSS 138 zum Einsatz, der sogar direkt auf die Leiterplatte des Bedienteils gelötet werden kann - entsprechende Landing Pads sind vorhanden. ==PWM im Auto== Obwohl ich PWM grundsätzlich mag, muss eine Einschränkung gemacht werden: Im Auto kann sie mehr als störend wirken. Grund hierfür sind zum Einen die im Auto auftretenden Vibrationen und die Tatsache, dass man (hoffentlich) öfter mal hin und her schaut. Bei diesen Bewegungen kann (im Zusammenhang mit der Nachbildwirkung des Auges) ein unangenehmes bis irritierendes Flackern entstehen. In diesem Zusammenhang frage ich mich ernsthaft, was manche Entwickler bei Autoherstellern zu sich genommen haben - bei vielen neuen (und auch hochklassigen) Autos kann man diesen Effekt bei den Rück-, Brems- und Tagfahrlichtern wahrnehmen, was sehr von der eigentlichen Sache ablenkt. ==Software== {{Infobox AVR | Typ = ATtiny45 | Takt = 8 | FuseH = DD | FuseL = C2 | FuseE = FE }} Die Software muss eigentlich nur drei Aufgaben erfüllen: Umgebungshelligkeit messen, den auszugebenen Helligkeitswert ermitteln und den Hardware-PWM füttern. Keine große Aufgabe. Da momentan nur ein ATTiny45 in kleinem Package herumliegt, muss dieser schon fast verwendet werden. Einen Vorteil hat die Größe des verwendeten Mikrocontrollers: Man muss in der Software nichts optimieren und trotzdem ist noch genügend Platz für einen Bootloader. Hierfür kommt fastboot von Peter Dannegger, der sich schon bei anderen Projekten als sehr zuverlässig erwiesen hat. Damit die Helligkeit der LEDs nicht direkt der Umgebungshelligkeit und dem Rauschen des ADCs folgt, wird der Ausgabewert je Endlosschleifendurchlauf immer nur um eins zum Zielwert hin inkrementiert bzw. dekrementiert. Mit einer zusätzlichen Verzögerung dimmt die Beleuchtung relativ angenehm nach oben oder unten. Ursprünglich wollte ich zusätzlich noch einen Näherungssensor (kapazitiv, siehe Touchlight) in den Code einbauen, damit die Bedienelemente heller werden, wenn man die Hand annähert. Da dies aber schon auf dem Schreibtisch nicht so recht funktionieren wollte und im Auto meistens eine deutlich schlechtere Umgebung anzunehmen ist (und ich nicht unnötig viel Zeit reinblasen wollte), ließ ich die Spielerei dann doch sein. Die PWM-Frequenz ist übrigens sehr hoch gewählt. Die CPU läuft mit 8MHz und der Prescaler des Timers auf 1 gestellt. Da das Register 8 bit lang ist, ergibt sich eine Zykluszeit von 256 Takten - stolze 31kHz. Da flackert garantiert nichts. ==Hardware== Wie bereits weiter oben geschrieben, kommt ein kleiner ATTiny45 zum Einsatz. Rx und Tx für den Bootloader und Debug wurden auf PB3 und PB4 gelegt, wodurch alle für den Bootloader benötigten Pins (Reset, Rx, Tx und GND) auf einer Seite des ICs liegen. Zum Anschluss des "Programmers" wurde eine 1,27mm Buchsenleiste direkt an den Chip angelötet. Auf der anderen Seite ist der FET für die LEDs (am Output Compare) und die Fotodiode angeschlossen. Der N-FET für die LEDs ist über einen 10k-Widerstand angeschlossen, am ADCx-Pin (PBx) die Fotodiode. Für den nötigen Strom durch sie sorgt ein 47k-Widerstand. Zusätzlich befinden sich zwei Kondensatoren zur Glättung bzw. Filterung von Störungen direkt am AVR. Eine Platine ist nicht nötig, auch hier wird alles direkt an die IC-Beinchen gelötet. <gallery> Datei:sony_bootloader_flash.jpg|Aufbau zum Flashen des Bootloader Datei:sony_aufbau.jpg|Fertiger Aufbau </gallery> Damit es zu keinen Kollisionen im Gehäuse kommt, legte ich die Leiterplatte und die Rückseite des Gehäuses nochmal auf den Scanner und ließ die Bildbearbeitung rödeln, um gefährliche Stellen zu markieren: <gallery> Datei:sony_einbau.jpg|Unterer Gehäuseteil mit Kollisionsbereichen Datei:sony_bot_komplett.jpg|Unterseite Platine (gespiegelt) </gallery> =Stromversorgung= Ohne Stromversorgung für den Mikrocontroller bleiben die LEDs dunkel. Dass Strom im Bedienteil vorhanden ist, ist klar. Aber wo und vor allem wie viel? Nachdem das Autoradio zerlegt auf dem Schreibtisch war, konnte ich die vorkommenden Spannungen sehr bequem messen. Im Bedienteil kommen drei Spannungsschienen an: 3,3V für den Displaytreiber, 5V für den USB-Port und 10,5V für die LEDs. So richtig konnte ich mich nicht entscheiden, aus was der Mikrocontroller versorgt werden soll. 10,5V sind blöd, weil ein Spannungsregler fällig geworden wäre, bei 3,3V hat der FET einen größeren Drain-Source-Widerstand und bei den 5V vom USB weiß man nicht genau, ob sie immer zur Verfügung stehen. Im Zweifel halt doch das, was am ehesten passt. 5V und fertig. ==Test/Parametrisierung== Damit es dem Mikrocontroller nicht komplett langweilig ist und man die Kennlinie für die Helligkeit etwas einfacher anpassen kann, gibt die Firmware des Mikrocontrollers den aktuell eingelesenen Helligkeitswert und den aktuellen Ziel- und Istwert der PWM per Soft-UART aus. Im Nachhinein hätte ich mir die Kennlinie fast sparen können. Durch geschickte Wahl des Widerstands für die Fotodiode ist die Umsetzung mit 1:1 (fast) ideal. Lediglich PWM-Wert 0 habe ich ausgeschlossen, da die Einschaltzeit zu kurz ist, um die weißen LEDs zum Leuchten zu bringen, wohingegen die blauen schon etwas von sich geben. =Download= 0f3f6dbaeeffd8af15b166b28be4e768e147d032 815 812 2012-09-26T20:17:34Z Chris 2 Stromlaufplan & Download hinzugefügt wikitext text/x-wiki Über die übertrieben helle Hintergrundbeleuchtung in meinem Autoradio und dessen vorübergehenden Lösung habe ich mich ja bereits vor geraumer Zeit im Blog ausgelassen. Dass nichts für die Ewigkeit ist, gilt natürlich auch für viele Kleber. So kam es, dass dessen Wirkung auf den "Verdunkelungsstreifen" nachließ und diese ihren Platz verließen. Resultat: ich werde wieder geblendet. Um eine längerfristige Lösung zu erhalten, entschied ich mich, das Problem selbst und nicht dessen Symptome zu behandeln. Die LEDs sollen nachhaltig abgedunkelt werden - da ich nicht genau weiß, was ich vor mir hab heißt es: Bedienteil abnehmen und genauer unter die Lupe nehmen. =Untersuchung= Ein paar Schrauben und Klipse später liegt die Leiterplatte auf dem Tisch. Um die Schaltung besser analysieren zu können, kommt die Kamera und Bildbearbeitung ins Spiel: Fotos von der Ober- und Unterseite in der Bildbearbeitung möglichst deckungsgleich übereinandergelegt erleichtern die Arbeit ungemein. Auf drei zusätzlichen Ebenen befinden sich nachgezeichneten Leiterbahnen und die Durchkontaktierungen. Zwei weitere beinhalten die interessanten Bauteile auf den jeweiligen Seiten: <gallery> Datei:sony_top.jpg|Oberseite Datei:sony_top_leiterbahnen.jpg|Oberseite mit Leiterbahnen Datei:sony_bot.jpg|Unterseite (gespiegelt) Datei:sony_bot_leiterbahnen.jpg| Unterseite mit Leiterbahnen Datei:sony_leiterbahnen.png|Leiterbahnen & Bauteile hervorgehoben </gallery> Eine kleine Anmerkung zu abnehmbaren Bedienteilen (zumindest bei Sony): Blödsinn. Ok, man sieht nicht, um welches Radio es sich handelt und es ist auf den ersten Blick unbrauchbar, kann man jedoch ein anderes Bedienteil ergattern, bringt man es auf jeden Fall wieder zum Laufen. Zumindest konnte ich bei meinem keinen Cryptochip oder etwas in diese Richtung entdecken. Der Displaycontroller (LC irgendwas) hat auch nichts in dieser Richtung integriert. Wie dem auch sei, zumindest wurde ich bei der Schaltung für die LEDs fündig - hier haben die Damen und Herren bei Sony mitgedacht: die Masse aller Leuchtdioden führt über einen 0-Ohm-Widerstand. Dieser durch einen Schalter ersetzt lässt sich die Beleuchtung sehr rudimentär steuern. ==Mehr Einblicke== Nachdem mir das Suchen nach Versorgungsspannungen nur Anhand des Bedienteils zu blöd wurde beschloss ich, mir den Rest vom Radio anzusehen. An der Front des bedienteillosen Radios befinden sich 4 Schrauben - was ich nicht wusste: nur eine hält die Front. Die restlichen halten den Auswurfmechanismus für das Bedienteil (links) und das Mikrofon für die Freisprecheinrichtung (warum dieses sich ausgerechnet hinter dem Bedienteil befindet, konnte ich bis heute nicht herausfinden). Diese habe ich leider so weit gelöst, dass das Mikrofon wegfiel. Da ich nicht wusste, ob es nicht doch eine Schraube des CD-Laufwerks war, kam zur Sicherheit das gesamte Radio mal an die frische Luft. Der Ausbau ist ganz einfach: Blenden der A-Säule abnehmen, Ablage vorne entfernen, drei Halteschrauben für die Mittelkonsole raus drehen, das CD-Fach öffnen, zwei Blenden abnehmen und dort zwei Schrauben lösen und abschließend unter der Mittelkonsole nochmal zwei Schrauben entfernen. Nun kann die Mittelkonsole herausgenommen werden, bei der zuerst die beiden "Lüftungsschlitze" herausgeklipst werden müssen um an die Schrauben des Radios zu kommen. An diesem müssen dann nur noch 4 weitere Schrauben heraus gedreht werden. Damit man das Modul nun ohne Gewalt raus ziehen zu können, kann man noch zwei weitere Schrauben lösen. Alles ganz einfach. Zumindest bin ich mir sehr sicher, dass das Radio der letzte Gegenstand in meinem Auto ist, der gestohlen wird. Dafür trennen nur noch 3 weitere Schrauben den vollen Blick in das Innenleben der Blechbüchse. Ganz nett ist das CD-Laufwerk, das einfach auf die Hauptplatine gesteckt ist. Ist dieses nicht vorhanden, lässt sich das Radio größtenteils verwenden, allerdings fehlt neben der CD auch die USB-Quelle. Genauer betrachtet ist dies sogar mehr als naheliegend: Genauso wie von CD kann der Player vom USB-Stick aus MP3-, AAC- und WMA-Dateien wiedergeben. So unterschiedlich ist das Zeug also nicht, warum sollte man also doppelten Aufwand betreiben? Interessant am Innenleben ist auch die Bestückung der Quarze: Diese sind nicht (wie sonst üblich) möglichst nah an der Platine, sondern stehen gute 5mm in der Luft. Vermutlich wird dadurch versucht, die mechanische Kopplung (Vibrationen) etwas zu verringern. Schließlich müssen Quarze frei schwingen können. Was ich jedoch nicht ganz verstehe, ist das Mikrofon und das Bluetooth-Modul. Ok, das Radio kommt aus Japan, dementsprechend wurde es wohl für Rechtslenker gebaut. Warum gibt es aber keine europäische Version (Mikro links)? Zumal man die Gussform für die Front so machen könnte, dass man das Mikrofon auf beiden Seiten montieren könnte. Whatever. Beim BT-Modul ist verwunderlich, dass dessen Antenne tatsächlich abgetrennt vom Rest ist. Ob die Antenne nun rechts, links, oben oder unten im Gehäuse ist, dürfte relativ egal sein. Hier wurde eine dünne Koax-Leitung und sogar diese unsäglichen U.FL-Buchsen ("Druckknöpfe") verbaut. Kostenoptimierung sieht anders aus. <gallery> Datei:sony_intern.jpg|Sony BT3700U von innen Datei:sony_cdlw.jpg|CD-Laufwerk von unten </gallery> =Verbesserung= An/Aus kann die Beleuchtung nun schon, aber das kann es natürlich nicht gewesen sein. Wie eingangs beschrieben, es sollte was Vernünftiges werden. Wer mich kennt weiß: ein Mikrocontroller muss her, denn: jedes Popelgerät hat mittlerweile einen Umgebungslichtsensor, so soll es auch mit dem Radio geschehen. ==Lichtsensor== Das größte Problem hierbei ist erst einmal: Was wo unterbringen? Dem Mikrocontroller ist es primär egal, wo er werkelt. Nur die Helligkeit sollte da gemessen werden, wo sie her kommt. Zunächst ist allerdings die Frage, welches Bauteil kann/soll verwendet werden. Im Sortierkasten sieht’s mau aus, Reichelt hat ein paar feine Bauteile, die aber eigentlich alle ein bisschen zu groß sind. Geworden ist es dann ein BPW 16N, der für seine bedrahtete Natur relativ klein ist. Das was wäre zumindest teilweise geklärt, bleibt das "Wo". Leider ist die Frontplatte an fast allen Stellen mit Beschriftung oder Bedienelement versehen, einzig zwischen Display und USB-Port befindet sich eine auch von unten relativ gut zugängliche Stelle. Was hier fehlt ist natürlich die Transparenz. Dafür kann mit Proxxon und Schleifkopf gesorgt werden. Mit niedriger Drehzahl und Fingerspitzengefühl ging es der Plaste an den Kragen. Da ich nur ein Sichtfenster und kein Loch wollte, hieß es immer wieder absetzen und Tiefe kontrollieren. Nach 4 Nachbohrungen war endlich ein Licht am Ende des "Tunnels" zu sehen. An der B-Note (Sauberkeit des Sichtfensters) könnte ich zwar noch ein bisschen arbeiten, für meine Anforderungen genügte die Qualität allerdings: <gallery> Datei:sony_lichtloch.jpg|Gebohrtes Lichtloch Datei:sony_front.jpg|Gebohrtes Lichtloch von oben Datei:sony_fotodiode.jpg|Gelötete Fotodiode Datei:sony_fotodiode_eingebaut.jpg|Fotodiode eingebaut </gallery> ==Ansteuerung== [[Bild:sony_fet.jpg|thumb|Aufgelöteter FET mit Gatewiderstand]] Auf LED-Seite sieht die Sache schon ein wenig anders aus. Da die Elektronik ein paar LEDs ein- und ausschalten kann, würde eine Stromquelle für gegenläufiges Blinken der restlichen Leuchtdioden sorgen. Zudem ist eine Stromquelle vergleichsweise groß und für diesen Zweck etwas übertrieben. Aus diesen Gründen soll Pulsweitenmodulation eingesetzt werden. Zum Schalten kommt der im SOT-23-Gehäuse verfügbare BSS 138 zum Einsatz, der sogar direkt auf die Leiterplatte des Bedienteils gelötet werden kann - entsprechende Landing Pads sind vorhanden. ==PWM im Auto== Obwohl ich PWM grundsätzlich mag, muss eine Einschränkung gemacht werden: Im Auto kann sie mehr als störend wirken. Grund hierfür sind zum Einen die im Auto auftretenden Vibrationen und die Tatsache, dass man (hoffentlich) öfter mal hin und her schaut. Bei diesen Bewegungen kann (im Zusammenhang mit der Nachbildwirkung des Auges) ein unangenehmes bis irritierendes Flackern entstehen. In diesem Zusammenhang frage ich mich ernsthaft, was manche Entwickler bei Autoherstellern zu sich genommen haben - bei vielen neuen (und auch hochklassigen) Autos kann man diesen Effekt bei den Rück-, Brems- und Tagfahrlichtern wahrnehmen, was sehr von der eigentlichen Sache ablenkt. ==Software== {{Infobox AVR | Typ = ATtiny45 | Takt = 8 | FuseH = DD | FuseL = C2 | FuseE = FE }} Die Software muss eigentlich nur drei Aufgaben erfüllen: Umgebungshelligkeit messen, den auszugebenen Helligkeitswert ermitteln und den Hardware-PWM füttern. Keine große Aufgabe. Da momentan nur ein ATTiny45 in kleinem Package herumliegt, muss dieser schon fast verwendet werden. Einen Vorteil hat die Größe des verwendeten Mikrocontrollers: Man muss in der Software nichts optimieren und trotzdem ist noch genügend Platz für einen Bootloader. Hierfür kommt fastboot von Peter Dannegger, der sich schon bei anderen Projekten als sehr zuverlässig erwiesen hat. Damit die Helligkeit der LEDs nicht direkt der Umgebungshelligkeit und dem Rauschen des ADCs folgt, wird der Ausgabewert je Endlosschleifendurchlauf immer nur um eins zum Zielwert hin inkrementiert bzw. dekrementiert. Mit einer zusätzlichen Verzögerung dimmt die Beleuchtung relativ angenehm nach oben oder unten. Ursprünglich wollte ich zusätzlich noch einen Näherungssensor (kapazitiv, siehe Touchlight) in den Code einbauen, damit die Bedienelemente heller werden, wenn man die Hand annähert. Da dies aber schon auf dem Schreibtisch nicht so recht funktionieren wollte und im Auto meistens eine deutlich schlechtere Umgebung anzunehmen ist (und ich nicht unnötig viel Zeit reinblasen wollte), ließ ich die Spielerei dann doch sein. Die PWM-Frequenz ist übrigens sehr hoch gewählt. Die CPU läuft mit 8MHz und der Prescaler des Timers auf 1 gestellt. Da das Register 8 bit lang ist, ergibt sich eine Zykluszeit von 256 Takten - stolze 31kHz. Da flackert garantiert nichts. ==Hardware== [[Bild:sony_schem.jpg|thumb|Stromlaufplan]] Wie bereits weiter oben geschrieben, kommt ein kleiner ATTiny45 zum Einsatz. Rx und Tx für den Bootloader und Debug wurden auf PB3 und PB4 gelegt, wodurch alle für den Bootloader benötigten Pins (Reset, Rx, Tx und GND) auf einer Seite des ICs liegen. Zum Anschluss des "Programmers" wurde eine 1,27mm Buchsenleiste direkt an den Chip angelötet. Auf der anderen Seite ist der FET für die LEDs (am Output Compare) und die Fotodiode angeschlossen. Der N-FET für die LEDs ist über einen 10k-Widerstand angeschlossen, am ADCx-Pin (PBx) die Fotodiode. Für den nötigen Strom durch sie sorgt ein 47k-Widerstand. Zusätzlich befinden sich zwei Kondensatoren zur Glättung bzw. Filterung von Störungen direkt am AVR. Eine Platine ist nicht nötig, auch hier wird alles direkt an die IC-Beinchen gelötet. <gallery> Datei:sony_bootloader_flash.jpg|Aufbau zum Flashen des Bootloader Datei:sony_aufbau.jpg|Fertiger Aufbau </gallery> Damit es zu keinen Kollisionen im Gehäuse kommt, legte ich die Leiterplatte und die Rückseite des Gehäuses nochmal auf den Scanner und ließ die Bildbearbeitung rödeln, um gefährliche Stellen zu markieren: <gallery> Datei:sony_einbau.jpg|Unterer Gehäuseteil mit Kollisionsbereichen Datei:sony_bot_komplett.jpg|Unterseite Platine (gespiegelt) </gallery> =Stromversorgung= Ohne Stromversorgung für den Mikrocontroller bleiben die LEDs dunkel. Dass Strom im Bedienteil vorhanden ist, ist klar. Aber wo und vor allem wie viel? Nachdem das Autoradio zerlegt auf dem Schreibtisch war, konnte ich die vorkommenden Spannungen sehr bequem messen. Im Bedienteil kommen drei Spannungsschienen an: 3,3V für den Displaytreiber, 5V für den USB-Port und 10,5V für die LEDs. So richtig konnte ich mich nicht entscheiden, aus was der Mikrocontroller versorgt werden soll. 10,5V sind blöd, weil ein Spannungsregler fällig geworden wäre, bei 3,3V hat der FET einen größeren Drain-Source-Widerstand und bei den 5V vom USB weiß man nicht genau, ob sie immer zur Verfügung stehen. Im Zweifel halt doch das, was am ehesten passt. 5V und fertig. ==Test/Parametrisierung== Damit es dem Mikrocontroller nicht komplett langweilig ist und man die Kennlinie für die Helligkeit etwas einfacher anpassen kann, gibt die Firmware des Mikrocontrollers den aktuell eingelesenen Helligkeitswert und den aktuellen Ziel- und Istwert der PWM per Soft-UART aus. Im Nachhinein hätte ich mir die Kennlinie fast sparen können. Durch geschickte Wahl des Widerstands für die Fotodiode ist die Umsetzung mit 1:1 (fast) ideal. Lediglich PWM-Wert 0 habe ich ausgeschlossen, da die Einschaltzeit zu kurz ist, um die weißen LEDs zum Leuchten zu bringen, wohingegen die blauen schon etwas von sich geben. =Download= [[Datei:sony_dimm.zip]] Bootloader, Firmware & Stromlaufplan c148fedccaf36ad4c2fe1be8f048b8afd9ced4b5 816 815 2012-09-26T20:31:00Z Chris 2 Überschriften korrigiert, YouTube-Link hinzugefügt wikitext text/x-wiki Über die übertrieben helle Hintergrundbeleuchtung in meinem Autoradio und dessen vorübergehenden Lösung habe ich mich ja bereits vor geraumer Zeit im Blog ausgelassen. Dass nichts für die Ewigkeit ist, gilt natürlich auch für viele Kleber. So kam es, dass dessen Wirkung auf den "Verdunkelungsstreifen" nachließ und diese ihren Platz verließen. Resultat: ich werde wieder geblendet. Um eine längerfristige Lösung zu erhalten, entschied ich mich, das Problem selbst und nicht dessen Symptome zu behandeln. Die LEDs sollen nachhaltig abgedunkelt werden - da ich nicht genau weiß, was ich vor mir hab heißt es: Bedienteil abnehmen und genauer unter die Lupe nehmen. =Untersuchung= Ein paar Schrauben und Klipse später liegt die Leiterplatte auf dem Tisch. Um die Schaltung besser analysieren zu können, kommt die Kamera und Bildbearbeitung ins Spiel: Fotos von der Ober- und Unterseite in der Bildbearbeitung möglichst deckungsgleich übereinandergelegt erleichtern die Arbeit ungemein. Auf drei zusätzlichen Ebenen befinden sich nachgezeichneten Leiterbahnen und die Durchkontaktierungen. Zwei weitere beinhalten die interessanten Bauteile auf den jeweiligen Seiten: <gallery> Datei:sony_top.jpg|Oberseite Datei:sony_top_leiterbahnen.jpg|Oberseite mit Leiterbahnen Datei:sony_bot.jpg|Unterseite (gespiegelt) Datei:sony_bot_leiterbahnen.jpg| Unterseite mit Leiterbahnen Datei:sony_leiterbahnen.png|Leiterbahnen & Bauteile hervorgehoben </gallery> Eine kleine Anmerkung zu abnehmbaren Bedienteilen (zumindest bei Sony): Blödsinn. Ok, man sieht nicht, um welches Radio es sich handelt und es ist auf den ersten Blick unbrauchbar, kann man jedoch ein anderes Bedienteil ergattern, bringt man es auf jeden Fall wieder zum Laufen. Zumindest konnte ich bei meinem keinen Cryptochip oder etwas in diese Richtung entdecken. Der Displaycontroller (LC irgendwas) hat auch nichts in dieser Richtung integriert. Wie dem auch sei, zumindest wurde ich bei der Schaltung für die LEDs fündig - hier haben die Damen und Herren bei Sony mitgedacht: die Masse aller Leuchtdioden führt über einen 0-Ohm-Widerstand. Dieser durch einen Schalter ersetzt lässt sich die Beleuchtung sehr rudimentär steuern. ==Mehr Einblicke== Nachdem mir das Suchen nach Versorgungsspannungen nur Anhand des Bedienteils zu blöd wurde beschloss ich, mir den Rest vom Radio anzusehen. An der Front des bedienteillosen Radios befinden sich 4 Schrauben - was ich nicht wusste: nur eine hält die Front. Die restlichen halten den Auswurfmechanismus für das Bedienteil (links) und das Mikrofon für die Freisprecheinrichtung (warum dieses sich ausgerechnet hinter dem Bedienteil befindet, konnte ich bis heute nicht herausfinden). Diese habe ich leider so weit gelöst, dass das Mikrofon wegfiel. Da ich nicht wusste, ob es nicht doch eine Schraube des CD-Laufwerks war, kam zur Sicherheit das gesamte Radio mal an die frische Luft. Der Ausbau ist ganz einfach: Blenden der A-Säule abnehmen, Ablage vorne entfernen, drei Halteschrauben für die Mittelkonsole raus drehen, das CD-Fach öffnen, zwei Blenden abnehmen und dort zwei Schrauben lösen und abschließend unter der Mittelkonsole nochmal zwei Schrauben entfernen. Nun kann die Mittelkonsole herausgenommen werden, bei der zuerst die beiden "Lüftungsschlitze" herausgeklipst werden müssen um an die Schrauben des Radios zu kommen. An diesem müssen dann nur noch 4 weitere Schrauben heraus gedreht werden. Damit man das Modul nun ohne Gewalt raus ziehen zu können, kann man noch zwei weitere Schrauben lösen. Alles ganz einfach. Zumindest bin ich mir sehr sicher, dass das Radio der letzte Gegenstand in meinem Auto ist, der gestohlen wird. Dafür trennen nur noch 3 weitere Schrauben den vollen Blick in das Innenleben der Blechbüchse. Ganz nett ist das CD-Laufwerk, das einfach auf die Hauptplatine gesteckt ist. Ist dieses nicht vorhanden, lässt sich das Radio größtenteils verwenden, allerdings fehlt neben der CD auch die USB-Quelle. Genauer betrachtet ist dies sogar mehr als naheliegend: Genauso wie von CD kann der Player vom USB-Stick aus MP3-, AAC- und WMA-Dateien wiedergeben. So unterschiedlich ist das Zeug also nicht, warum sollte man also doppelten Aufwand betreiben? Interessant am Innenleben ist auch die Bestückung der Quarze: Diese sind nicht (wie sonst üblich) möglichst nah an der Platine, sondern stehen gute 5mm in der Luft. Vermutlich wird dadurch versucht, die mechanische Kopplung (Vibrationen) etwas zu verringern. Schließlich müssen Quarze frei schwingen können. Was ich jedoch nicht ganz verstehe, ist das Mikrofon und das Bluetooth-Modul. Ok, das Radio kommt aus Japan, dementsprechend wurde es wohl für Rechtslenker gebaut. Warum gibt es aber keine europäische Version (Mikro links)? Zumal man die Gussform für die Front so machen könnte, dass man das Mikrofon auf beiden Seiten montieren könnte. Whatever. Beim BT-Modul ist verwunderlich, dass dessen Antenne tatsächlich abgetrennt vom Rest ist. Ob die Antenne nun rechts, links, oben oder unten im Gehäuse ist, dürfte relativ egal sein. Hier wurde eine dünne Koax-Leitung und sogar diese unsäglichen U.FL-Buchsen ("Druckknöpfe") verbaut. Kostenoptimierung sieht anders aus. <gallery> Datei:sony_intern.jpg|Sony BT3700U von innen Datei:sony_cdlw.jpg|CD-Laufwerk von unten </gallery> =Verbesserung= An/Aus kann die Beleuchtung nun schon, aber das kann es natürlich nicht gewesen sein. Wie eingangs beschrieben, es sollte was Vernünftiges werden. Wer mich kennt weiß: ein Mikrocontroller muss her, denn: jedes Popelgerät hat mittlerweile einen Umgebungslichtsensor, so soll es auch mit dem Radio geschehen. ==Lichtsensor== Das größte Problem hierbei ist erst einmal: Was wo unterbringen? Dem Mikrocontroller ist es primär egal, wo er werkelt. Nur die Helligkeit sollte da gemessen werden, wo sie her kommt. Zunächst ist allerdings die Frage, welches Bauteil kann/soll verwendet werden. Im Sortierkasten sieht’s mau aus, Reichelt hat ein paar feine Bauteile, die aber eigentlich alle ein bisschen zu groß sind. Geworden ist es dann ein BPW 16N, der für seine bedrahtete Natur relativ klein ist. Das was wäre zumindest teilweise geklärt, bleibt das "Wo". Leider ist die Frontplatte an fast allen Stellen mit Beschriftung oder Bedienelement versehen, einzig zwischen Display und USB-Port befindet sich eine auch von unten relativ gut zugängliche Stelle. Was hier fehlt ist natürlich die Transparenz. Dafür kann mit Proxxon und Schleifkopf gesorgt werden. Mit niedriger Drehzahl und Fingerspitzengefühl ging es der Plaste an den Kragen. Da ich nur ein Sichtfenster und kein Loch wollte, hieß es immer wieder absetzen und Tiefe kontrollieren. Nach 4 Nachbohrungen war endlich ein Licht am Ende des "Tunnels" zu sehen. An der B-Note (Sauberkeit des Sichtfensters) könnte ich zwar noch ein bisschen arbeiten, für meine Anforderungen genügte die Qualität allerdings: <gallery> Datei:sony_lichtloch.jpg|Gebohrtes Lichtloch Datei:sony_front.jpg|Gebohrtes Lichtloch von oben Datei:sony_fotodiode.jpg|Gelötete Fotodiode Datei:sony_fotodiode_eingebaut.jpg|Fotodiode eingebaut </gallery> ==Ansteuerung== [[Bild:sony_fet.jpg|thumb|Aufgelöteter FET mit Gatewiderstand]] Auf LED-Seite sieht die Sache schon ein wenig anders aus. Da die Elektronik ein paar LEDs ein- und ausschalten kann, würde eine Stromquelle für gegenläufiges Blinken der restlichen Leuchtdioden sorgen. Zudem ist eine Stromquelle vergleichsweise groß und für diesen Zweck etwas übertrieben. Aus diesen Gründen soll Pulsweitenmodulation eingesetzt werden. Zum Schalten kommt der im SOT-23-Gehäuse verfügbare BSS 138 zum Einsatz, der sogar direkt auf die Leiterplatte des Bedienteils gelötet werden kann - entsprechende Landing Pads sind vorhanden. ==PWM im Auto== Obwohl ich PWM grundsätzlich mag, muss eine Einschränkung gemacht werden: Im Auto kann sie mehr als störend wirken. Grund hierfür sind zum Einen die im Auto auftretenden Vibrationen und die Tatsache, dass man (hoffentlich) öfter mal hin und her schaut. Bei diesen Bewegungen kann (im Zusammenhang mit der Nachbildwirkung des Auges) ein unangenehmes bis irritierendes Flackern entstehen. In diesem Zusammenhang frage ich mich ernsthaft, was manche Entwickler bei Autoherstellern zu sich genommen haben - bei vielen neuen (und auch hochklassigen) Autos kann man diesen Effekt bei den Rück-, Brems- und Tagfahrlichtern wahrnehmen, was sehr von der eigentlichen Sache ablenkt. ==Software== {{Infobox AVR | Typ = ATtiny45 | Takt = 8 | FuseH = DD | FuseL = C2 | FuseE = FE }} Die Software muss eigentlich nur drei Aufgaben erfüllen: Umgebungshelligkeit messen, den auszugebenen Helligkeitswert ermitteln und den Hardware-PWM füttern. Keine große Aufgabe. Da momentan nur ein ATTiny45 in kleinem Package herumliegt, muss dieser schon fast verwendet werden. Einen Vorteil hat die Größe des verwendeten Mikrocontrollers: Man muss in der Software nichts optimieren und trotzdem ist noch genügend Platz für einen Bootloader. Hierfür kommt fastboot von Peter Dannegger, der sich schon bei anderen Projekten als sehr zuverlässig erwiesen hat. Damit die Helligkeit der LEDs nicht direkt der Umgebungshelligkeit und dem Rauschen des ADCs folgt, wird der Ausgabewert je Endlosschleifendurchlauf immer nur um eins zum Zielwert hin inkrementiert bzw. dekrementiert. Mit einer zusätzlichen Verzögerung dimmt die Beleuchtung relativ angenehm nach oben oder unten. Ursprünglich wollte ich zusätzlich noch einen Näherungssensor (kapazitiv, siehe Touchlight) in den Code einbauen, damit die Bedienelemente heller werden, wenn man die Hand annähert. Da dies aber schon auf dem Schreibtisch nicht so recht funktionieren wollte und im Auto meistens eine deutlich schlechtere Umgebung anzunehmen ist (und ich nicht unnötig viel Zeit reinblasen wollte), ließ ich die Spielerei dann doch sein. Die PWM-Frequenz ist übrigens sehr hoch gewählt. Die CPU läuft mit 8MHz und der Prescaler des Timers auf 1 gestellt. Da das Register 8 bit lang ist, ergibt sich eine Zykluszeit von 256 Takten - stolze 31kHz. Da flackert garantiert nichts. ==Hardware== [[Bild:sony_schem.jpg|thumb|Stromlaufplan]] Wie bereits weiter oben geschrieben, kommt ein kleiner ATTiny45 zum Einsatz. Rx und Tx für den Bootloader und Debug wurden auf PB3 und PB4 gelegt, wodurch alle für den Bootloader benötigten Pins (Reset, Rx, Tx und GND) auf einer Seite des ICs liegen. Zum Anschluss des "Programmers" wurde eine 1,27mm Buchsenleiste direkt an den Chip angelötet. Auf der anderen Seite ist der FET für die LEDs (am Output Compare) und die Fotodiode angeschlossen. Der N-FET für die LEDs ist über einen 10k-Widerstand angeschlossen, am ADCx-Pin (PBx) die Fotodiode. Für den nötigen Strom durch sie sorgt ein 47k-Widerstand. Zusätzlich befinden sich zwei Kondensatoren zur Glättung bzw. Filterung von Störungen direkt am AVR. Eine Platine ist nicht nötig, auch hier wird alles direkt an die IC-Beinchen gelötet. <gallery> Datei:sony_bootloader_flash.jpg|Aufbau zum Flashen des Bootloader Datei:sony_aufbau.jpg|Fertiger Aufbau </gallery> Damit es zu keinen Kollisionen im Gehäuse kommt, legte ich die Leiterplatte und die Rückseite des Gehäuses nochmal auf den Scanner und ließ die Bildbearbeitung rödeln, um gefährliche Stellen zu markieren: <gallery> Datei:sony_einbau.jpg|Unterer Gehäuseteil mit Kollisionsbereichen Datei:sony_bot_komplett.jpg|Unterseite Platine (gespiegelt) </gallery> ==Stromversorgung== Ohne Stromversorgung für den Mikrocontroller bleiben die LEDs dunkel. Dass Strom im Bedienteil vorhanden ist, ist klar. Aber wo und vor allem wie viel? Nachdem das Autoradio zerlegt auf dem Schreibtisch war, konnte ich die vorkommenden Spannungen sehr bequem messen. Im Bedienteil kommen drei Spannungsschienen an: 3,3V für den Displaytreiber, 5V für den USB-Port und 10,5V für die LEDs. So richtig konnte ich mich nicht entscheiden, aus was der Mikrocontroller versorgt werden soll. 10,5V sind blöd, weil ein Spannungsregler fällig geworden wäre, bei 3,3V hat der FET einen größeren Drain-Source-Widerstand und bei den 5V vom USB weiß man nicht genau, ob sie immer zur Verfügung stehen. Im Zweifel halt doch das, was am ehesten passt. 5V und fertig. ==Test/Parametrisierung== Damit es dem Mikrocontroller nicht komplett langweilig ist und man die Kennlinie für die Helligkeit etwas einfacher anpassen kann, gibt die Firmware des Mikrocontrollers den aktuell eingelesenen Helligkeitswert und den aktuellen Ziel- und Istwert der PWM per Soft-UART aus. Im Nachhinein hätte ich mir die Kennlinie fast sparen können. Durch geschickte Wahl des Widerstands für die Fotodiode ist die Umsetzung mit 1:1 (fast) ideal. Lediglich PWM-Wert 0 habe ich ausgeschlossen, da die Einschaltzeit zu kurz ist, um die weißen LEDs zum Leuchten zu bringen, wohingegen die blauen schon etwas von sich geben. =Video= Natürlich gibt es auch ein Video vom Test auf [http://www.youtube.com/watch?v=4NmjCZ1zjsk YouTube] =Download= [[Datei:sony_dimm.zip]] Bootloader, Firmware & Stromlaufplan 5015174d718ef33276948993b67aa55f372242d1 822 816 2012-10-18T16:57:26Z Chris 2 /* Hardware */ Stromlaufplan korrigiert wikitext text/x-wiki Über die übertrieben helle Hintergrundbeleuchtung in meinem Autoradio und dessen vorübergehenden Lösung habe ich mich ja bereits vor geraumer Zeit im Blog ausgelassen. Dass nichts für die Ewigkeit ist, gilt natürlich auch für viele Kleber. So kam es, dass dessen Wirkung auf den "Verdunkelungsstreifen" nachließ und diese ihren Platz verließen. Resultat: ich werde wieder geblendet. Um eine längerfristige Lösung zu erhalten, entschied ich mich, das Problem selbst und nicht dessen Symptome zu behandeln. Die LEDs sollen nachhaltig abgedunkelt werden - da ich nicht genau weiß, was ich vor mir hab heißt es: Bedienteil abnehmen und genauer unter die Lupe nehmen. =Untersuchung= Ein paar Schrauben und Klipse später liegt die Leiterplatte auf dem Tisch. Um die Schaltung besser analysieren zu können, kommt die Kamera und Bildbearbeitung ins Spiel: Fotos von der Ober- und Unterseite in der Bildbearbeitung möglichst deckungsgleich übereinandergelegt erleichtern die Arbeit ungemein. Auf drei zusätzlichen Ebenen befinden sich nachgezeichneten Leiterbahnen und die Durchkontaktierungen. Zwei weitere beinhalten die interessanten Bauteile auf den jeweiligen Seiten: <gallery> Datei:sony_top.jpg|Oberseite Datei:sony_top_leiterbahnen.jpg|Oberseite mit Leiterbahnen Datei:sony_bot.jpg|Unterseite (gespiegelt) Datei:sony_bot_leiterbahnen.jpg| Unterseite mit Leiterbahnen Datei:sony_leiterbahnen.png|Leiterbahnen & Bauteile hervorgehoben </gallery> Eine kleine Anmerkung zu abnehmbaren Bedienteilen (zumindest bei Sony): Blödsinn. Ok, man sieht nicht, um welches Radio es sich handelt und es ist auf den ersten Blick unbrauchbar, kann man jedoch ein anderes Bedienteil ergattern, bringt man es auf jeden Fall wieder zum Laufen. Zumindest konnte ich bei meinem keinen Cryptochip oder etwas in diese Richtung entdecken. Der Displaycontroller (LC irgendwas) hat auch nichts in dieser Richtung integriert. Wie dem auch sei, zumindest wurde ich bei der Schaltung für die LEDs fündig - hier haben die Damen und Herren bei Sony mitgedacht: die Masse aller Leuchtdioden führt über einen 0-Ohm-Widerstand. Dieser durch einen Schalter ersetzt lässt sich die Beleuchtung sehr rudimentär steuern. ==Mehr Einblicke== Nachdem mir das Suchen nach Versorgungsspannungen nur Anhand des Bedienteils zu blöd wurde beschloss ich, mir den Rest vom Radio anzusehen. An der Front des bedienteillosen Radios befinden sich 4 Schrauben - was ich nicht wusste: nur eine hält die Front. Die restlichen halten den Auswurfmechanismus für das Bedienteil (links) und das Mikrofon für die Freisprecheinrichtung (warum dieses sich ausgerechnet hinter dem Bedienteil befindet, konnte ich bis heute nicht herausfinden). Diese habe ich leider so weit gelöst, dass das Mikrofon wegfiel. Da ich nicht wusste, ob es nicht doch eine Schraube des CD-Laufwerks war, kam zur Sicherheit das gesamte Radio mal an die frische Luft. Der Ausbau ist ganz einfach: Blenden der A-Säule abnehmen, Ablage vorne entfernen, drei Halteschrauben für die Mittelkonsole raus drehen, das CD-Fach öffnen, zwei Blenden abnehmen und dort zwei Schrauben lösen und abschließend unter der Mittelkonsole nochmal zwei Schrauben entfernen. Nun kann die Mittelkonsole herausgenommen werden, bei der zuerst die beiden "Lüftungsschlitze" herausgeklipst werden müssen um an die Schrauben des Radios zu kommen. An diesem müssen dann nur noch 4 weitere Schrauben heraus gedreht werden. Damit man das Modul nun ohne Gewalt raus ziehen zu können, kann man noch zwei weitere Schrauben lösen. Alles ganz einfach. Zumindest bin ich mir sehr sicher, dass das Radio der letzte Gegenstand in meinem Auto ist, der gestohlen wird. Dafür trennen nur noch 3 weitere Schrauben den vollen Blick in das Innenleben der Blechbüchse. Ganz nett ist das CD-Laufwerk, das einfach auf die Hauptplatine gesteckt ist. Ist dieses nicht vorhanden, lässt sich das Radio größtenteils verwenden, allerdings fehlt neben der CD auch die USB-Quelle. Genauer betrachtet ist dies sogar mehr als naheliegend: Genauso wie von CD kann der Player vom USB-Stick aus MP3-, AAC- und WMA-Dateien wiedergeben. So unterschiedlich ist das Zeug also nicht, warum sollte man also doppelten Aufwand betreiben? Interessant am Innenleben ist auch die Bestückung der Quarze: Diese sind nicht (wie sonst üblich) möglichst nah an der Platine, sondern stehen gute 5mm in der Luft. Vermutlich wird dadurch versucht, die mechanische Kopplung (Vibrationen) etwas zu verringern. Schließlich müssen Quarze frei schwingen können. Was ich jedoch nicht ganz verstehe, ist das Mikrofon und das Bluetooth-Modul. Ok, das Radio kommt aus Japan, dementsprechend wurde es wohl für Rechtslenker gebaut. Warum gibt es aber keine europäische Version (Mikro links)? Zumal man die Gussform für die Front so machen könnte, dass man das Mikrofon auf beiden Seiten montieren könnte. Whatever. Beim BT-Modul ist verwunderlich, dass dessen Antenne tatsächlich abgetrennt vom Rest ist. Ob die Antenne nun rechts, links, oben oder unten im Gehäuse ist, dürfte relativ egal sein. Hier wurde eine dünne Koax-Leitung und sogar diese unsäglichen U.FL-Buchsen ("Druckknöpfe") verbaut. Kostenoptimierung sieht anders aus. <gallery> Datei:sony_intern.jpg|Sony BT3700U von innen Datei:sony_cdlw.jpg|CD-Laufwerk von unten </gallery> =Verbesserung= An/Aus kann die Beleuchtung nun schon, aber das kann es natürlich nicht gewesen sein. Wie eingangs beschrieben, es sollte was Vernünftiges werden. Wer mich kennt weiß: ein Mikrocontroller muss her, denn: jedes Popelgerät hat mittlerweile einen Umgebungslichtsensor, so soll es auch mit dem Radio geschehen. ==Lichtsensor== Das größte Problem hierbei ist erst einmal: Was wo unterbringen? Dem Mikrocontroller ist es primär egal, wo er werkelt. Nur die Helligkeit sollte da gemessen werden, wo sie her kommt. Zunächst ist allerdings die Frage, welches Bauteil kann/soll verwendet werden. Im Sortierkasten sieht’s mau aus, Reichelt hat ein paar feine Bauteile, die aber eigentlich alle ein bisschen zu groß sind. Geworden ist es dann ein BPW 16N, der für seine bedrahtete Natur relativ klein ist. Das was wäre zumindest teilweise geklärt, bleibt das "Wo". Leider ist die Frontplatte an fast allen Stellen mit Beschriftung oder Bedienelement versehen, einzig zwischen Display und USB-Port befindet sich eine auch von unten relativ gut zugängliche Stelle. Was hier fehlt ist natürlich die Transparenz. Dafür kann mit Proxxon und Schleifkopf gesorgt werden. Mit niedriger Drehzahl und Fingerspitzengefühl ging es der Plaste an den Kragen. Da ich nur ein Sichtfenster und kein Loch wollte, hieß es immer wieder absetzen und Tiefe kontrollieren. Nach 4 Nachbohrungen war endlich ein Licht am Ende des "Tunnels" zu sehen. An der B-Note (Sauberkeit des Sichtfensters) könnte ich zwar noch ein bisschen arbeiten, für meine Anforderungen genügte die Qualität allerdings: <gallery> Datei:sony_lichtloch.jpg|Gebohrtes Lichtloch Datei:sony_front.jpg|Gebohrtes Lichtloch von oben Datei:sony_fotodiode.jpg|Gelötete Fotodiode Datei:sony_fotodiode_eingebaut.jpg|Fotodiode eingebaut </gallery> ==Ansteuerung== [[Bild:sony_fet.jpg|thumb|Aufgelöteter FET mit Gatewiderstand]] Auf LED-Seite sieht die Sache schon ein wenig anders aus. Da die Elektronik ein paar LEDs ein- und ausschalten kann, würde eine Stromquelle für gegenläufiges Blinken der restlichen Leuchtdioden sorgen. Zudem ist eine Stromquelle vergleichsweise groß und für diesen Zweck etwas übertrieben. Aus diesen Gründen soll Pulsweitenmodulation eingesetzt werden. Zum Schalten kommt der im SOT-23-Gehäuse verfügbare BSS 138 zum Einsatz, der sogar direkt auf die Leiterplatte des Bedienteils gelötet werden kann - entsprechende Landing Pads sind vorhanden. ==PWM im Auto== Obwohl ich PWM grundsätzlich mag, muss eine Einschränkung gemacht werden: Im Auto kann sie mehr als störend wirken. Grund hierfür sind zum Einen die im Auto auftretenden Vibrationen und die Tatsache, dass man (hoffentlich) öfter mal hin und her schaut. Bei diesen Bewegungen kann (im Zusammenhang mit der Nachbildwirkung des Auges) ein unangenehmes bis irritierendes Flackern entstehen. In diesem Zusammenhang frage ich mich ernsthaft, was manche Entwickler bei Autoherstellern zu sich genommen haben - bei vielen neuen (und auch hochklassigen) Autos kann man diesen Effekt bei den Rück-, Brems- und Tagfahrlichtern wahrnehmen, was sehr von der eigentlichen Sache ablenkt. ==Software== {{Infobox AVR | Typ = ATtiny45 | Takt = 8 | FuseH = DD | FuseL = C2 | FuseE = FE }} Die Software muss eigentlich nur drei Aufgaben erfüllen: Umgebungshelligkeit messen, den auszugebenen Helligkeitswert ermitteln und den Hardware-PWM füttern. Keine große Aufgabe. Da momentan nur ein ATTiny45 in kleinem Package herumliegt, muss dieser schon fast verwendet werden. Einen Vorteil hat die Größe des verwendeten Mikrocontrollers: Man muss in der Software nichts optimieren und trotzdem ist noch genügend Platz für einen Bootloader. Hierfür kommt fastboot von Peter Dannegger, der sich schon bei anderen Projekten als sehr zuverlässig erwiesen hat. Damit die Helligkeit der LEDs nicht direkt der Umgebungshelligkeit und dem Rauschen des ADCs folgt, wird der Ausgabewert je Endlosschleifendurchlauf immer nur um eins zum Zielwert hin inkrementiert bzw. dekrementiert. Mit einer zusätzlichen Verzögerung dimmt die Beleuchtung relativ angenehm nach oben oder unten. Ursprünglich wollte ich zusätzlich noch einen Näherungssensor (kapazitiv, siehe Touchlight) in den Code einbauen, damit die Bedienelemente heller werden, wenn man die Hand annähert. Da dies aber schon auf dem Schreibtisch nicht so recht funktionieren wollte und im Auto meistens eine deutlich schlechtere Umgebung anzunehmen ist (und ich nicht unnötig viel Zeit reinblasen wollte), ließ ich die Spielerei dann doch sein. Die PWM-Frequenz ist übrigens sehr hoch gewählt. Die CPU läuft mit 8MHz und der Prescaler des Timers auf 1 gestellt. Da das Register 8 bit lang ist, ergibt sich eine Zykluszeit von 256 Takten - stolze 31kHz. Da flackert garantiert nichts. ==Hardware== [[Datei:Sony_schem.png|thumb|Stromlaufplan]] Wie bereits weiter oben geschrieben, kommt ein kleiner ATTiny45 zum Einsatz. Rx und Tx für den Bootloader und Debug wurden auf PB3 und PB4 gelegt, wodurch alle für den Bootloader benötigten Pins (Reset, Rx, Tx und GND) auf einer Seite des ICs liegen. Zum Anschluss des "Programmers" wurde eine 1,27mm Buchsenleiste direkt an den Chip angelötet. Auf der anderen Seite ist der FET für die LEDs (am Output Compare) und die Fotodiode angeschlossen. Der N-FET für die LEDs ist über einen 10k-Widerstand angeschlossen, am ADCx-Pin (PBx) die Fotodiode. Für den nötigen Strom durch sie sorgt ein 47k-Widerstand. Zusätzlich befinden sich zwei Kondensatoren zur Glättung bzw. Filterung von Störungen direkt am AVR. Eine Platine ist nicht nötig, auch hier wird alles direkt an die IC-Beinchen gelötet. <gallery> Datei:sony_bootloader_flash.jpg|Aufbau zum Flashen des Bootloader Datei:sony_aufbau.jpg|Fertiger Aufbau </gallery> Damit es zu keinen Kollisionen im Gehäuse kommt, legte ich die Leiterplatte und die Rückseite des Gehäuses nochmal auf den Scanner und ließ die Bildbearbeitung rödeln, um gefährliche Stellen zu markieren: <gallery> Datei:sony_einbau.jpg|Unterer Gehäuseteil mit Kollisionsbereichen Datei:sony_bot_komplett.jpg|Unterseite Platine (gespiegelt) </gallery> ==Stromversorgung== Ohne Stromversorgung für den Mikrocontroller bleiben die LEDs dunkel. Dass Strom im Bedienteil vorhanden ist, ist klar. Aber wo und vor allem wie viel? Nachdem das Autoradio zerlegt auf dem Schreibtisch war, konnte ich die vorkommenden Spannungen sehr bequem messen. Im Bedienteil kommen drei Spannungsschienen an: 3,3V für den Displaytreiber, 5V für den USB-Port und 10,5V für die LEDs. So richtig konnte ich mich nicht entscheiden, aus was der Mikrocontroller versorgt werden soll. 10,5V sind blöd, weil ein Spannungsregler fällig geworden wäre, bei 3,3V hat der FET einen größeren Drain-Source-Widerstand und bei den 5V vom USB weiß man nicht genau, ob sie immer zur Verfügung stehen. Im Zweifel halt doch das, was am ehesten passt. 5V und fertig. ==Test/Parametrisierung== Damit es dem Mikrocontroller nicht komplett langweilig ist und man die Kennlinie für die Helligkeit etwas einfacher anpassen kann, gibt die Firmware des Mikrocontrollers den aktuell eingelesenen Helligkeitswert und den aktuellen Ziel- und Istwert der PWM per Soft-UART aus. Im Nachhinein hätte ich mir die Kennlinie fast sparen können. Durch geschickte Wahl des Widerstands für die Fotodiode ist die Umsetzung mit 1:1 (fast) ideal. Lediglich PWM-Wert 0 habe ich ausgeschlossen, da die Einschaltzeit zu kurz ist, um die weißen LEDs zum Leuchten zu bringen, wohingegen die blauen schon etwas von sich geben. =Video= Natürlich gibt es auch ein Video vom Test auf [http://www.youtube.com/watch?v=4NmjCZ1zjsk YouTube] =Download= [[Datei:sony_dimm.zip]] Bootloader, Firmware & Stromlaufplan 0ef4925bfecd983067e5578250487e67348e64d0 Datei:Sony schem.png 6 329 813 2012-09-26T20:14:22Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Sony dimm.zip 6 330 814 2012-09-26T20:15:35Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Eagle toolbar sch.png 6 331 818 2012-10-11T19:35:57Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Eagle toolbar.zip 6 332 819 2012-10-11T20:04:10Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 EAGLE-Toolbar 0 333 820 2012-10-11T20:05:43Z Chris 2 Seite erstellt wikitext text/x-wiki Obwohl ich EAGLE sehr gerne mag, hat mich eines schon immer genervt: für jedes Bauteil muss man entweder im Control Panel suchen oder den ungefähren Namen wissen, um es über die Kommandozeile und ADD-Befehl hinzuzufügen. In den altbekannten Trash-Werbesendungen heißt es an dieser Stelle immer "[http://www.youtube.com/results?search_query=wunderharke+5000 Gibt's denn keine bessere Lösung?]" "Doch, jetzt gibt es eine." =Grundlage= EAGLE bietet ein Textmenü an, das sich seit einigen Versionen kaskadieren und sogar bebildern lässt. Die Definition dieser Menüs findet über den Befehl MENU statt. Dieser ist allerdings nicht persistent und nach einem Neustart von EAGLE findet man wieder das "alte" vor. Die beim Start von EAGLE festgelegten Menüs sind in der Startup-Datei eagle.scr im Verzeichnis /scr/ definiert. Diese kann man nach belieben anpassen und somit die am häufigsten verwendeten Befehle schnell zugänglich machen. =Anpassungen= ==Schematic-Editor== Die erste Anpassung fand im Schematic-Editor statt. Dort wurden in das Menü alle meine Standard-Bauteile hinzugefügt - zunächst als grundlegende Texteinträge. Nachdem das Zeug etwas gewachsen ist, beschloss ich, die Verknüpfungen etwas auszuweiten und die Bauteile in Untermenüs zu verlagern. Der Button für die einzelnen Menüs wird durch ein entsprechendes Bildchen verschönert: [[Datei:eagle_toolbar_sch.png]] Neben den Bauteilen lassen sich auch die Standard-Spannungs-Signale sowie ein SMD-Testpad (noch erweiterungsfähig) hinzugefügt werden. Mit dem letzten Button kann ein Screenshot mit 150dpi erstellt werden. ==Board-Editor== Hier fällt das Menü etwas spartaner aus. In der ersten "Funktionsgruppe" lässt sich das Grid in drei Stufen verändern: * Grob: 1,27mm (alternativ 0,635mm) * Mittel: 0,635mm (alternativ 0,3175mm) * Fein: 0,3175mm (alternativ 0,15875mm) Die Maße sind ganz klar auf das Routen von SMD-Bauteilen ausgerichtet und jeweils ein vielfaches von der MIL-Einheit. Mit den nächsten Buttons lassen sich die Top- und Bottom-Layer ein- und ausblenden Die Layer *Names und *Values bleiben davon unangetastet. Das liegt hauptsächlich daran, dass ich diese für das Routing selbst in aller Regel deaktiviere. Bei Bedarf können diese aber einfach in der Script-Datei hinzugefügt werden. Neben den Layern kann auch die Anzeige von Polygonen (wie z. B. Masseflächen umgeschaltet werden. Leider ist der Klick auf den Ausblenden-Buttons nur die halbe Miete: EAGLE rendert die Ansicht leider nicht neu und die Polygone müssen mit dem Ripup-Befehl zurückgesetzt werden. Einen Workaround hierfür habe ich noch nicht gefunden. Zu guter letzt lässt sich über die Toolbar noch das ULP "length-freq-ri.ulp" aufrufen, die gerade bei ein wenig kritischen Designs sehr nützlich ist. =Installation= Wenn man keine eigenen Anpassungen in EAGLE hat und mit meinen Einstellungen leben kann (Grid wird im Layout-Editor im 1,27mm Raster als Punkte dargestellt) kann man die Ordner in der ZIP-Datei direkt ins EAGLE-Verzeichnis werfen. Wer eigene Anpassungen in der scr-Datei hat, kann den /bin/-Ordner zunächst ohne Gefahr kopieren. Die eagle.scr-Dateien müssen jeweils mit einem Text-Editor geöffnet werden und manuell der Bereich zwischen den Kommentaren <pre> ### hobbyelektronik.org EAGLE-Toolbar ### </pre> in die eigene Datei (natürlich an die passende Stelle) kopiert werden. Achtung: Design-Link ist in "meiner" eagle.scr deaktiviert, da diese die zusätzlichen Buttons "aufbläht". Getestet wurde die Toolbar bis jetzt mit EAGLE 5.12.0 und 6.2.0 und wird vermutlich auch mit anderen Versionen funktionieren. =Download= [[Datei:Eagle_toolbar.zip]] [[Kategorie:Sonstiges]] [[Kategorie:Sofware]] 1cb5e3baa044146ceed415e547ab1722d9adb053 Benutzer:Chris 2 45 823 737 2012-11-15T22:30:23Z Chris 2 dies und das wikitext text/x-wiki = Wie es dazu kam = Irgendwann um 2003 fing ich damit an, meine (mehr oder weniger gelungenen) Bastel-Projekte in HTML zu verwandeln und auf hobby-elektronik.de.vu zu veröffentlichen. Der Speicherplatz bei Tripod wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich irgendwann, auf das schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10 April 2005 die Domain hobbyelektronik.org registriert. Zu .org kam es, da mir eine Woche davor jemand die .net-Domain weggeschnappte. Im Nachhinein bin ich glücklich, dem damaligen .net-Hype entgangen zu sein. Eine richtige Organisation sind wir zwar noch immer nicht aber was nicht ist, kann ja noch werden ;) = Was ich mache = Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" bezeichnen. Seit Oktober 2009 studiere ich Elektrotechnik/Nachrichtentechnik an der [http://www.hs-ulm.de Hochschule Ulm]. Die Schnittmenge bzw. vielmehr die Verbindung aus den beiden Bereichen kommen auch wieder in meinen Hobbys zusammen. = Warum das Ganze? = Ganz einfach: Weil es mir Spaß macht. Wie an anderer Stelle schon erwähnt, bezeichne ich diese Seite als "nicht-kommerzielles Umfeld". Damit ist gemeint, dass ich mit dieser Homepage kein Geld verdiene (keine Werbung, keine Partnerschaften mir irgendwelchen Firmen, etc.) und es ehrlich gesagt auch nicht will. Das bedeutet auch, dass Produkterwähnungen und evtl. auch Empfehlungen aus meiner eigenen Erfahrung und Meinung gemacht werden. (Wer spenden will - gerne auch Sachspenden - ist natürlich willkommen ;)). Neben dem Spaß geht es mir auch darum, etwas an andere Bastler, Elektronik-Einsteiger und DICH weiter- bzw. zurückzugeben. Auch ich habe mal sehr klein angefangen und war froh um alles, was mich näher in Richtung Computer und Elektronik brachte (und auch heute noch bringt). Wenn man so will, kann man es als Kreislauf verstehen :) [http://sprut.de/misc/hpphilos.htm Sprut] hat es meiner Meinung mit seiner Homepage-Philosophie sehr gut getroffen. = Kannst du mir... = ...bei <Thema hier einsetzen> helfen? Jein. Wenn du ehrliches Interesse hast, helfe ich gerne. Was ich allerdings überhaupt nicht abkann ist die "Mach mal-" bzw. "Freibiermentalität", die manche an den Tag legen. Solche können erst wiederkommen, wenn ich einen Gewerbeschein habe... = Kontakt = Solltest du Fragen, Kritik, Verbesserungsvorschläge oder Fehler auf den Seiten hier gefunden haben - eine kleine Mail genügt und wird gerne beantwortet: chris at hobbyelektronik punkt org Wer mich in sozialen Netzwerken sucht, wird wenig erfolg haben. Will ich nicht, mach ich nicht. (siehe auch [[Hobbyelektronik.org:Impressum|Impressum]]) 45363078b8f576b3e22719e84f2c3f50cc18c7a4 824 823 2012-11-30T12:05:43Z Chris 2 /* Was ich mache */ wikitext text/x-wiki = Wie es dazu kam = Irgendwann um 2003 fing ich damit an, meine (mehr oder weniger gelungenen) Bastel-Projekte in HTML zu verwandeln und auf hobby-elektronik.de.vu zu veröffentlichen. Der Speicherplatz bei Tripod wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich irgendwann, auf das schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10 April 2005 die Domain hobbyelektronik.org registriert. Zu .org kam es, da mir eine Woche davor jemand die .net-Domain weggeschnappte. Im Nachhinein bin ich glücklich, dem damaligen .net-Hype entgangen zu sein. Eine richtige Organisation sind wir zwar noch immer nicht aber was nicht ist, kann ja noch werden ;) = Was ich mache = Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" bezeichnen. Seit Oktober 2009 studiere ich Elektrotechnik/Nachrichtentechnik an der [http://www.hs-ulm.de Hochschule Ulm]. Die Schnittmenge bzw. vielmehr die Verbindung aus den beiden Bereichen kommen auch wieder in meinen Hobbys zusammen. Seit September 2012 bin ich Kleinunternehmer und repariere nebenzu Computer, wobei ein weiterer - für Besucher dieser Homepage interessantere - Geschäftsbereich geplant ist. Abseits vom Schreibtisch findet man mich ab und zu hinter der Spiegelreflex, (viel zu selten) auf dem Rad oder in weit entfernten Ländern. Ein paar Eindrücke davon kann man auf den Fehlerseiten dieser Homepage finden. = Warum das Ganze? = Ganz einfach: Weil es mir Spaß macht. Wie an anderer Stelle schon erwähnt, bezeichne ich diese Seite als "nicht-kommerzielles Umfeld". Damit ist gemeint, dass ich mit dieser Homepage kein Geld verdiene (keine Werbung, keine Partnerschaften mir irgendwelchen Firmen, etc.) und es ehrlich gesagt auch nicht will. Das bedeutet auch, dass Produkterwähnungen und evtl. auch Empfehlungen aus meiner eigenen Erfahrung und Meinung gemacht werden. (Wer spenden will - gerne auch Sachspenden - ist natürlich willkommen ;)). Neben dem Spaß geht es mir auch darum, etwas an andere Bastler, Elektronik-Einsteiger und DICH weiter- bzw. zurückzugeben. Auch ich habe mal sehr klein angefangen und war froh um alles, was mich näher in Richtung Computer und Elektronik brachte (und auch heute noch bringt). Wenn man so will, kann man es als Kreislauf verstehen :) [http://sprut.de/misc/hpphilos.htm Sprut] hat es meiner Meinung mit seiner Homepage-Philosophie sehr gut getroffen. = Kannst du mir... = ...bei <Thema hier einsetzen> helfen? Jein. Wenn du ehrliches Interesse hast, helfe ich gerne. Was ich allerdings überhaupt nicht abkann ist die "Mach mal-" bzw. "Freibiermentalität", die manche an den Tag legen. Solche können erst wiederkommen, wenn ich einen Gewerbeschein habe... = Kontakt = Solltest du Fragen, Kritik, Verbesserungsvorschläge oder Fehler auf den Seiten hier gefunden haben - eine kleine Mail genügt und wird gerne beantwortet: chris at hobbyelektronik punkt org Wer mich in sozialen Netzwerken sucht, wird wenig erfolg haben. Will ich nicht, mach ich nicht. (siehe auch [[Hobbyelektronik.org:Impressum|Impressum]]) ecaa75871c4143382783dd3edfcbd09854272f26 AVR-Doper/FAQ 0 334 825 2012-12-06T16:09:30Z Chris 2 Die Seite wurde neu angelegt: „==Was ist der AVR-Doper und was kann er?== Der AVR-Doper ist ein Programmiergerät für AVR-Mikrocontroller (8Bit), die die Programmiermodi SPI und HVSP unters…“ wikitext text/x-wiki ==Was ist der AVR-Doper und was kann er?== Der AVR-Doper ist ein Programmiergerät für AVR-Mikrocontroller (8Bit), die die Programmiermodi SPI und HVSP unterstützen. Er ist Protokollkompatibel zum STK500 und unterstützt einen HID-Modus (Jumper muss vor dem Einstecken gesetzt werden), in dem er keinen Treiber braucht, jedoch nur von entsprechender Software (z. B. AVRdude) bedient werden kann. ==Läuft mein AVR-Doper unter Windows 7?== Ja, aber es erfordert (je nach Verwendung) Tricks. Genaueres ist im [[AVR-Doper#AVR-Doper_unter_Windows_7|Hauptartikel]] beschrieben. Meine Empfehlung unter Windows 7: den HID-Modus in Verbindung mit AVRdude verwenden. Das erspart Frickelei und Ärger. ==Läuft der Doper in AVR Studio 5/Atmel Studio 6?== Bei meinen Versuchen hat es nicht funktioniert, aber das muss nichts heißen. Mit der Zeit bin ich dazu übergegangen, den Doper über AVRdude in Verbindung mit einer Batch-Datei anzusprechen. Über das Tools-Menü in AVR/Atmel Studio lässt sich der Aufruf hierfür relativ einfach integrieren. ==Gibt es zum Doper ein Manual?== Mir wäre nichts bekannt. ==Wie kann ich testen, ob mein AVR-Doper funktioniert?== Das eindeutigste Zeichen für die Funktion ist, dass er am PC erkannt wird und Mikrocontroller beschreiben kann, was dann auch der vollen Funktion entspricht. Die LED Leuchtet nur, wenn auf den Ziel-Chip zugegriffen wird. Weiter kann man die Funktion grundlegend feststellen, indem man kontrolliert, ob an der Kathode von D3 ungefähr 12V anliegen. ==Für was ist welche Buchse gut?== SV1 ist das ISP-Interface (In Circuit Programmig). Also im Prinzip der Hauptgrund, wofür man den Doper gebaut hat. Die Pinbelegung ist abweichend vom "de-facto-Standard", da an Pin 8 und 10 ein UART zur Verfügung gestellt wird. Diese Pins liegen bei anderen Designs auf Masse. SV2 ist für die HVSP (High Voltage Serial Programming). Dies ist besonders interessant, wenn man den Reset-Pin als I/O benutzen möchte. Dazu kann man die Fuse RSTDISBL aktivieren. Das HVSP ist zudem an den Sockeln IC3 und IC4 herausgeführt, sodass man für die kleinen AVRs keinen extra Adapter braucht. Wichtig bei der HVSP ist, dass über die entsprechende Download-Software der Modus auch aktiviert/verwendet wird. ==Was muss ich machen, damit der Doper an meinem Computer funktioniert?== Die entsprechenden Treiber installieren. Nach dem ersten Anschließen sollte der Treiber-Installations-Dialog erscheinen. Bei der Treiberquelle auf Erweitert klicken und die entsprechende INF-Datei (avrdoper.inf bzw. avrdoper-vista.inf) aus dem dekomprimierten Projektarchiv auswählen. Windows 7-User müssen etwas mehr machen: [[AVR-Doper#AVR-Doper_unter_Windows_7|AVR-Doper unter Windows 7]]. ==Muss ich deinen Patch fürs AVR-Studio anwenden?== Nein. 23a72a0c04e7e838808a9559208525338053194f 827 825 2012-12-08T13:54:08Z Chris 2 wikitext text/x-wiki ==Was ist der AVR-Doper und was kann er?== Der AVR-Doper ist ein Programmiergerät für AVR-Mikrocontroller (8Bit), die die Programmiermodi SPI und HVSP unterstützen. Er ist Protokollkompatibel zum STK500 und unterstützt einen HID-Modus (Jumper muss vor dem Einstecken gesetzt werden), in dem er keinen Treiber braucht, jedoch nur von entsprechender Software (z. B. AVRdude) bedient werden kann. ==Läuft mein AVR-Doper unter Windows 7?== Ja, aber es erfordert (je nach Verwendung) Tricks. Genaueres ist im [[AVR-Doper#AVR-Doper_unter_Windows_7|Hauptartikel]] beschrieben. Meine Empfehlung unter Windows 7: den HID-Modus in Verbindung mit AVRdude verwenden. Das erspart Frickelei und Ärger. ==Läuft der Doper in AVR Studio 5/Atmel Studio 6?== Bei meinen Versuchen hat es nicht funktioniert, aber das muss nichts heißen. Mit der Zeit bin ich dazu übergegangen, den Doper über AVRdude in Verbindung mit einer Batch-Datei anzusprechen. Über das Tools-Menü in AVR/Atmel Studio lässt sich der Aufruf hierfür relativ einfach integrieren. ==Gibt es zum Doper ein Manual?== Mir wäre nichts bekannt. Allerdings sind die meisten Dokumentationen des STK500 (zumindest softwareseitig) auch für den AVR-Doper gültig, wenn er im STK500-Modus betrieben wird. ==Wie kann ich testen, ob mein AVR-Doper funktioniert?== Das eindeutigste Zeichen für die Funktion ist, dass er am PC erkannt wird und Mikrocontroller beschreiben kann, was dann auch der vollen Funktion entspricht. Die LED Leuchtet nur, wenn auf den Ziel-Chip zugegriffen wird. Weiter kann man die Funktion grundlegend feststellen, indem man kontrolliert, ob an der Kathode von D3 ungefähr 12V anliegen. ==Für was ist welche Buchse gut?== SV1 ist das ISP-Interface (In Circuit Programmig). Also im Prinzip der Hauptgrund, wofür man den Doper gebaut hat. Die Pinbelegung ist abweichend vom "de-facto-Standard", da an Pin 8 und 10 ein UART zur Verfügung gestellt wird. Diese Pins liegen bei anderen Designs auf Masse. SV2 ist für die HVSP (High Voltage Serial Programming). Dies ist besonders interessant, wenn man den Reset-Pin als I/O benutzen möchte. Dazu kann man die Fuse RSTDISBL aktivieren. Das HVSP ist zudem an den Sockeln IC3 und IC4 herausgeführt, sodass man für die kleinen AVRs keinen extra Adapter braucht. Wichtig bei der HVSP ist, dass über die entsprechende Download-Software der Modus auch aktiviert/verwendet wird. ==Was muss ich machen, damit der Doper an meinem Computer funktioniert?== Die entsprechenden Treiber installieren. Nach dem ersten Anschließen sollte der Treiber-Installations-Dialog erscheinen. Bei der Treiberquelle auf Erweitert klicken und die entsprechende INF-Datei (avrdoper.inf bzw. avrdoper-vista.inf) aus dem dekomprimierten Projektarchiv auswählen. Windows 7-User müssen etwas mehr machen: [[AVR-Doper#AVR-Doper_unter_Windows_7|AVR-Doper unter Windows 7]]. ==Muss ich deinen Patch fürs AVR-Studio anwenden?== Nein. ==Wie muss ich welchen Jumper setzen?== (ja, das wurde wirklich gefragt) Im Prinzip steht es im Stromlaufplan. Wenn JP1 geschlossen ist, wird die Zielschaltung über den ISP-Port (SV1) mit 5V versorgt. Mit Schließen des JP2 kann man den Programmiertakt (SCK) reduzieren, falls man eine lange Leitung hat oder auf Nummer sicher gehen will. Ein geschlossener JP3 aktiviert den HID-Modus (siehe weiter oben) - sofern man ihn vor dem Anschließen des Dopers an den PC gesetzt hat. ==Wie verwende ich den Doper?== Es gibt zwar wenig Dokumentation über den AVR-Doper, aber das gibt es. Tipp: readme.txt ist ein ernstzunehmendes Angebot. 635d7199d0eca7c9e4b9f0f4739738aba9626533 Raspberry Pi IO 0 304 828 779 2012-12-31T09:34:04Z Chris 2 Typos wikitext text/x-wiki [[Datei:Raspberry io.jpg|200px|thumb|Raspberry Pi mit angeschlossenen LEDs]] Ich war einer der glücklichen, die einen der [http://hobbyelektronik.org/b/2012/04/er-ist-d/ ersten] [http://www.raspberrypi.org/ Raspberry Pi]s ergattern konnte. Zu meiner Schande muss ich gestehen, dass ich relativ lange gezögert habe, mich intensiver mit dem Computerchen zu beschäftigen. Interessant für Bastler ist auf jeden Fall die anschließbare Peripherie. Neben UART, SPI und I²C (für letztere existieren noch keine Treiber und ich bin leider noch zu blöd welche zu schreiben) existieren auch frei belegbare [http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 GPIOs] auf dem Board. =Erster Test= Das [http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29 Beispielprogramm] erfüllt seinen Zweck sehr gut. Nach ein wenig Herumspielen wollte ich wissen, wie schnell man denn die Bits wackeln lassen kann. Eine kleinere Änderung im Source lässt GPIO17 (bzw. "GPIO 0" an der Steckerbelegung - ich möchte nicht wissen, wer auf diese missverständliche Namensgebung gekommen ist) mit nahezu maximaler Frequenz 1000 Mal ein- und ausschalten. <source lang="c"> for (rep=0; rep<1000; rep++) { GPIO_SET = 1<<17; GPIO_CLR = 1<<17; } </source> Mit den Shellbefehlen <pre> gcc io.c sudo ./a.out </pre> Lässt sich der Code kompilieren und anschließend ausführen. Der Logic-Analyzer misst knapp 77ns Periodendauer, also 13MHz wobei ab und zu geringfügig größere Pausen entstehen, die die Frequenz auf 11MHz absinken lassen. Das ist trotzdem ganz respektabel! =Das Problem mit root= Das Beispielprogramm funktioniert also super, solange man es als root ausführt. Hinsichtlich der Sicherheit ist das jedoch etwas ungeschickt - wer möchte seine Programme dauerhaft als root ausführen? Besonders für mein Vorhaben eine ganz schlechte Idee: ich möchte als kleine Demonstration LEDs per Browser schalten lassen. Gleichzeitig verbietet der gesunde Menschenverstand, einen Webserver oder gar PHP als root-User laufen zu lassen (besonders in Hinblick auf die [http://heise.de/-1567906 schlechte] [http://heise.de/-1567433 Presse] in den letzten Tagen). Auch das /dev/mem-Interface möchte man nicht unbedingt fürs Userland freigeben (was zudem auch nicht funktioniert). Glücklicherweise kann man auf die GPIOs einzeln über virtuelle Dateien zugreifen. Das ist zwar nicht ganz so schnell, dafür kann man die virtuellen Dateien "normalen" Benutzern zugänglich machen. Dieses Zugänglichmachen findet für jeden Pin in 4 Schritten statt (hier am Beispiel von GPIO17): <pre> sudo echo "17" > /sys/class/gpio/export sudo echo "out" > /sys/class/gpio/gpio17/direction sudo chmod 555 /sys/class/gpio/gpio17/value sudo chmod 555 /sys/class/gpio/gpio17/direction </pre> Die letzten beiden Zeilen erlauben Lese- und Schreibzugriff für Besitzer (root), Gruppe (root) und jeden anderen. Alternativ kann man auch mit chown den Besitzer bzw. die Gruppe ändern, sodass man keinen Zugriff für jeden geben muss. In meinem Fall ist es aber (noch) egal. Um alle Ports auf einmal "freizugeben" habe ich eine kleines Shell-Script geschrieben, die dies erledigt: <pre> #!/bin/sh echo "17" > /sys/class/gpio/export echo "18" > /sys/class/gpio/export echo "21" > /sys/class/gpio/export echo "22" > /sys/class/gpio/export echo "23" > /sys/class/gpio/export echo "24" > /sys/class/gpio/export echo "25" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction echo "out" > /sys/class/gpio/gpio18/direction echo "out" > /sys/class/gpio/gpio21/direction echo "out" > /sys/class/gpio/gpio22/direction echo "out" > /sys/class/gpio/gpio23/direction echo "out" > /sys/class/gpio/gpio24/direction echo "out" > /sys/class/gpio/gpio25/direction chmod 666 /sys/class/gpio/gpio17/value chmod 666 /sys/class/gpio/gpio18/value chmod 666 /sys/class/gpio/gpio21/value chmod 666 /sys/class/gpio/gpio22/value chmod 666 /sys/class/gpio/gpio23/value chmod 666 /sys/class/gpio/gpio24/value chmod 666 /sys/class/gpio/gpio25/value chmod 666 /sys/class/gpio/gpio17/direction chmod 666 /sys/class/gpio/gpio18/direction chmod 666 /sys/class/gpio/gpio21/direction chmod 666 /sys/class/gpio/gpio22/direction chmod 666 /sys/class/gpio/gpio23/direction chmod 666 /sys/class/gpio/gpio24/direction chmod 666 /sys/class/gpio/gpio25/direction </pre> Für alle, die Linux nicht kennen: das "#!/bin/sh" am Anfang ist kein gewöhnlicher Kommentar, sondern ein [[wpde:Shebang|Shebang]], das der Bash (also der Konsole) sagt, mit was die Datei ausgeführt werden möchte. Wichtig ist auch, dass die Zeilenenden auf Linefeed (\n) und nicht auf Carrier Return+Linefeed eingestellt sind. Jeder gute Editor (z. B. Notepad++ oder SciTE) kann das. (Noch ein kleiner Hinweis: das 666 ist nichts satanisches, sondern die Berechtigung rw-rw-rw-, die es jedem Benutzer erlaubt, die virtuellen Dateien zu lesen und schreiben. Einen großen Dank an Y.T., der mich auf einen kleinen aber eklatanten Fehler hingewiesen hat) Wichtig ist anschließend, dass die Datei vor dem Start Ausführungsrechte bekommt: <pre> chmod 770 gpio.sh </pre> Anschließend kann man sie mit dem Befehl folgendem Befehl ausführen: <pre> sudo ./gpio </pre> '''Achtung''': Die Freigabe der GPIOs ist nicht persistent. Nach einem Neustart muss das Script erneut ausgeführt werden! =Webserver= Ein grundlegendes Element fehlt noch: der Webserver, den man wahrscheinlich am einfachsten mit [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] installiert. Hier die Befehle, die ich zur Installation von [http://www.lighttpd.net/ lighttpd] mit PHP5 verwendet habe (keine Garantie auf Funktionalität, Vollständigkeit und Korrektheit): <pre> sudo groupadd www-data sudo aptitude install lighttpd sudo aptitude install php5-cgi sudo lighty-enable-mod fastcgi sudo adduser pi www-data sudo chown -R www-data:www-data /var/www sudo chmod -R 775 /var/www </pre> Lighttpd habe ich deswegen gewählt, weil er (wie der Name suggeriert) etwas leichter und schneller als der mächtigere (aber etwas schwerfällige) Apache ist. Damit PHP funktioniert, muss in der Datei /etc/lighttpd/lighttpd.conf (wenn noch nicht vorhanden) durch das Ausführen von <pre> sudo nano /etc/lighttpd/lighttpd.conf </pre> folgender Text hinzugefügt werden: <pre> fastcgi.server = ( ".php" => (( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket" ))) </pre> Nach einem Server-Neustart mit <pre> sudo /etc/init.d/lighttpd force-reload </pre> sollte der Raspberry Pi per HTTP erreichbar sein. =Software= ==Server== Wie schon erwähnt läuft auf dem Server (oder sollte zumindest) PHP laufen. Da ich es nicht mag, Seiten wegen Kleinigkeiten neu zu laden, kommt ein [[wpde:Ajax (Programmierung)|Ajax]]/[http://json.org/ JSON]-Interface zum Einsatz. Dementsprechend fällt die Serversoftware minimalistisch aus. Beispielsweise übernimmt read.php das Lesen der Ports und deren Richtung. Die Informationen werden in ein assoziatives (Name => Wert) Array geschrieben, ins JSON-Format umgewandelt und an den Client ausgegeben: <source lang="php"> <?php $bits = array(17, 18, 21, 22, 23, 24, 25); $retval = array(); for($x = 0; $x < count($bits); $x++) { $bit = $bits[$x]; $val = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/value")); $dir = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/direction")); $val = $val == "1" ? 1 : 0; $dir = $dir == "out" ? "o" : "i"; $retval[] = array("bit" => $bit, "val" => $val, "dir" => $dir); } echo json_encode($retval); </source> ==Client== Den Client habe ich relativ schnell (und etwas schlampig) in JavaScript heruntergerissen. Wer etwas JavaScript und die vielen d.ebi, d.ac, d.ce und d.ctn irritiert - das sind Abkürzungen für häufig verwendete Befehle, die ich in common.js definiert habe: <source lang="javascript"> var d = { d : document, w : window, ebi : function(i) { return document.getElementById(i); }, ebn : function(n) { return document.getElementsByName(n); }, febn : function(n) { return document.getElementsByName(n)[0]; }, ce : function(n) { return document.createElement(n); }, ctn : function(n) { return document.createTextNode(n); }, ac : function(p, c) { return p.appendChild(c); }, ac1 : function(p, c) { p.appendChild(c); return p; } } </source> d.ebi steht zum Beispiel für '''d'''ocument.get'''E'''lement'''B'''y'''I'''d d.ac für '''d'''ocument.'''a'''ppend'''C'''hild usw... In diesem Sinne auch eine Entschuldigung an alle, die bei dem Klammer-Massaker einen Knoten im Hirn bekommen ;-) Dadurch, dass nahezu alles in JavaScript gemacht wird, ist der HTML-Body gähnend leer. Erst beim Laden wird der Seite Leben eingehaucht: <gallery> Datei:raspberry_io_gui.png|Benutzerinterface </gallery> Der Code erzeugt zunächst eine Tabelle, die dann durch Objekte von GpioPin gefüllt wird. Durch Klick auf die span-Elemente bzw. Bilder wird der Inhalt umgeschaltet und per XmlHttpRequest ein Kommando an den Server geschickt. Beim Klick auf Lesen wird ebenfalls per XmlHttpRequest eine Anfrage an den Server gesendet, wie oben erwähnt, mit einem JSON-String antwortet. Dies sieht dann z. B. wie folgt aus: <pre> [{"bit":17,"val":0,"dir":"o"},{"bit":18,"val":1,"dir":"o"},{"bit":21,"val":0,"dir":"o"},{"bit":22,"val":0,"dir":"i"},{"bit":23,"val":1,"dir":"i"},{"bit":24,"val":0,"dir":"o"},{"bit":25,"val":0,"dir":"o"}] </pre> Aufgedröselt wird die Struktur deutlicher: <source lang="javascript"> [ { "bit" : 17, "val" : 0, "dir" : "o" },{ "bit" : 18, "val" : 1, "dir" : "o" },{ "bit" : 21, "val" : 0, "dir" : "o" },{ ... } ] </source> Diese wird durch den JSON-parser in ein Objekt umgewandelt, per Schleife zugeordnet und durch die Funktion GpioPin::SetVals() gesetzt. Die Richtung und Wert kann man einfach durch Klick auf das jeweilige Element verändern. Durch einen Klick auf "Refresh" kann man die tatsächlichen Werte vom Server ermitteln, nach dem Aktivieren der Checkbox geschieht dies automatisch im Sekundentakt. Getestet wurde die die Anwendung bis jetzt im Firefox, "Standard" Android-Browser und dem aktuellen IE, wobei in letzterem die Aktualisierung nicht richtig funktioniert. <gallery> Datei:Raspberry_io_android.jpg|Raspberry Pi mit Tablet </gallery> =Download= [[Datei:Raspberry Pi IO.zip]] ==Hinweise== Der Inhalt der ZIP-Datei kann relativ einfach mit FileZilla auf den Raspberry (per SSH-Filetransfer) geschoben werden. Der Order IO muss unter /var/www/ liegen, gpio.sh an einem nahezu beliebigen Ort. Vor dem Ausführen der gpio.sh nicht vergessen, die Ausführungsrechte zu setzen! [[Kategorie:PC]] [[Kategorie:Raspberry Pi]] 045347303c81bc75b0d2297b69c12bc9e222e65f 829 828 2013-01-07T17:16:13Z Chris 2 /* Das Problem mit root */ Falsche Zugriffsrechte wikitext text/x-wiki [[Datei:Raspberry io.jpg|200px|thumb|Raspberry Pi mit angeschlossenen LEDs]] Ich war einer der glücklichen, die einen der [http://hobbyelektronik.org/b/2012/04/er-ist-d/ ersten] [http://www.raspberrypi.org/ Raspberry Pi]s ergattern konnte. Zu meiner Schande muss ich gestehen, dass ich relativ lange gezögert habe, mich intensiver mit dem Computerchen zu beschäftigen. Interessant für Bastler ist auf jeden Fall die anschließbare Peripherie. Neben UART, SPI und I²C (für letztere existieren noch keine Treiber und ich bin leider noch zu blöd welche zu schreiben) existieren auch frei belegbare [http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 GPIOs] auf dem Board. =Erster Test= Das [http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29 Beispielprogramm] erfüllt seinen Zweck sehr gut. Nach ein wenig Herumspielen wollte ich wissen, wie schnell man denn die Bits wackeln lassen kann. Eine kleinere Änderung im Source lässt GPIO17 (bzw. "GPIO 0" an der Steckerbelegung - ich möchte nicht wissen, wer auf diese missverständliche Namensgebung gekommen ist) mit nahezu maximaler Frequenz 1000 Mal ein- und ausschalten. <source lang="c"> for (rep=0; rep<1000; rep++) { GPIO_SET = 1<<17; GPIO_CLR = 1<<17; } </source> Mit den Shellbefehlen <pre> gcc io.c sudo ./a.out </pre> Lässt sich der Code kompilieren und anschließend ausführen. Der Logic-Analyzer misst knapp 77ns Periodendauer, also 13MHz wobei ab und zu geringfügig größere Pausen entstehen, die die Frequenz auf 11MHz absinken lassen. Das ist trotzdem ganz respektabel! =Das Problem mit root= Das Beispielprogramm funktioniert also super, solange man es als root ausführt. Hinsichtlich der Sicherheit ist das jedoch etwas ungeschickt - wer möchte seine Programme dauerhaft als root ausführen? Besonders für mein Vorhaben eine ganz schlechte Idee: ich möchte als kleine Demonstration LEDs per Browser schalten lassen. Gleichzeitig verbietet der gesunde Menschenverstand, einen Webserver oder gar PHP als root-User laufen zu lassen (besonders in Hinblick auf die [http://heise.de/-1567906 schlechte] [http://heise.de/-1567433 Presse] in den letzten Tagen). Auch das /dev/mem-Interface möchte man nicht unbedingt fürs Userland freigeben (was zudem auch nicht funktioniert). Glücklicherweise kann man auf die GPIOs einzeln über virtuelle Dateien zugreifen. Das ist zwar nicht ganz so schnell, dafür kann man die virtuellen Dateien "normalen" Benutzern zugänglich machen. Dieses Zugänglichmachen findet für jeden Pin in 4 Schritten statt (hier am Beispiel von GPIO17): <pre> sudo echo "17" > /sys/class/gpio/export sudo echo "out" > /sys/class/gpio/gpio17/direction sudo chmod 666 /sys/class/gpio/gpio17/value sudo chmod 666 /sys/class/gpio/gpio17/direction </pre> Die letzten beiden Zeilen erlauben Lese- und Schreibzugriff für Besitzer (root), Gruppe (root) und jeden anderen. Alternativ kann man auch mit chown den Besitzer bzw. die Gruppe ändern, sodass man keinen Zugriff für jeden geben muss. In meinem Fall ist es aber (noch) egal. Um alle Ports auf einmal "freizugeben" habe ich eine kleines Shell-Script geschrieben, die dies erledigt: <pre> #!/bin/sh echo "17" > /sys/class/gpio/export echo "18" > /sys/class/gpio/export echo "21" > /sys/class/gpio/export echo "22" > /sys/class/gpio/export echo "23" > /sys/class/gpio/export echo "24" > /sys/class/gpio/export echo "25" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction echo "out" > /sys/class/gpio/gpio18/direction echo "out" > /sys/class/gpio/gpio21/direction echo "out" > /sys/class/gpio/gpio22/direction echo "out" > /sys/class/gpio/gpio23/direction echo "out" > /sys/class/gpio/gpio24/direction echo "out" > /sys/class/gpio/gpio25/direction chmod 666 /sys/class/gpio/gpio17/value chmod 666 /sys/class/gpio/gpio18/value chmod 666 /sys/class/gpio/gpio21/value chmod 666 /sys/class/gpio/gpio22/value chmod 666 /sys/class/gpio/gpio23/value chmod 666 /sys/class/gpio/gpio24/value chmod 666 /sys/class/gpio/gpio25/value chmod 666 /sys/class/gpio/gpio17/direction chmod 666 /sys/class/gpio/gpio18/direction chmod 666 /sys/class/gpio/gpio21/direction chmod 666 /sys/class/gpio/gpio22/direction chmod 666 /sys/class/gpio/gpio23/direction chmod 666 /sys/class/gpio/gpio24/direction chmod 666 /sys/class/gpio/gpio25/direction </pre> Für alle, die Linux nicht kennen: das "#!/bin/sh" am Anfang ist kein gewöhnlicher Kommentar, sondern ein [[wpde:Shebang|Shebang]], das der Bash (also der Konsole) sagt, mit was die Datei ausgeführt werden möchte. Wichtig ist auch, dass die Zeilenenden auf Linefeed (\n) und nicht auf Carrier Return+Linefeed eingestellt sind. Jeder gute Editor (z. B. Notepad++ oder SciTE) kann das. (Noch ein kleiner Hinweis: das 666 ist nichts satanisches, sondern die Berechtigung rw-rw-rw-, die es jedem Benutzer erlaubt, die virtuellen Dateien zu lesen und schreiben. Einen großen Dank an Y.T., der mich auf einen kleinen aber eklatanten Fehler hingewiesen hat) Wichtig ist anschließend, dass die Datei vor dem Start Ausführungsrechte bekommt: <pre> chmod 770 gpio.sh </pre> Anschließend kann man sie mit dem Befehl folgendem Befehl ausführen: <pre> sudo ./gpio </pre> '''Achtung''': Die Freigabe der GPIOs ist nicht persistent. Nach einem Neustart muss das Script erneut ausgeführt werden! =Webserver= Ein grundlegendes Element fehlt noch: der Webserver, den man wahrscheinlich am einfachsten mit [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] installiert. Hier die Befehle, die ich zur Installation von [http://www.lighttpd.net/ lighttpd] mit PHP5 verwendet habe (keine Garantie auf Funktionalität, Vollständigkeit und Korrektheit): <pre> sudo groupadd www-data sudo aptitude install lighttpd sudo aptitude install php5-cgi sudo lighty-enable-mod fastcgi sudo adduser pi www-data sudo chown -R www-data:www-data /var/www sudo chmod -R 775 /var/www </pre> Lighttpd habe ich deswegen gewählt, weil er (wie der Name suggeriert) etwas leichter und schneller als der mächtigere (aber etwas schwerfällige) Apache ist. Damit PHP funktioniert, muss in der Datei /etc/lighttpd/lighttpd.conf (wenn noch nicht vorhanden) durch das Ausführen von <pre> sudo nano /etc/lighttpd/lighttpd.conf </pre> folgender Text hinzugefügt werden: <pre> fastcgi.server = ( ".php" => (( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket" ))) </pre> Nach einem Server-Neustart mit <pre> sudo /etc/init.d/lighttpd force-reload </pre> sollte der Raspberry Pi per HTTP erreichbar sein. =Software= ==Server== Wie schon erwähnt läuft auf dem Server (oder sollte zumindest) PHP laufen. Da ich es nicht mag, Seiten wegen Kleinigkeiten neu zu laden, kommt ein [[wpde:Ajax (Programmierung)|Ajax]]/[http://json.org/ JSON]-Interface zum Einsatz. Dementsprechend fällt die Serversoftware minimalistisch aus. Beispielsweise übernimmt read.php das Lesen der Ports und deren Richtung. Die Informationen werden in ein assoziatives (Name => Wert) Array geschrieben, ins JSON-Format umgewandelt und an den Client ausgegeben: <source lang="php"> <?php $bits = array(17, 18, 21, 22, 23, 24, 25); $retval = array(); for($x = 0; $x < count($bits); $x++) { $bit = $bits[$x]; $val = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/value")); $dir = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/direction")); $val = $val == "1" ? 1 : 0; $dir = $dir == "out" ? "o" : "i"; $retval[] = array("bit" => $bit, "val" => $val, "dir" => $dir); } echo json_encode($retval); </source> ==Client== Den Client habe ich relativ schnell (und etwas schlampig) in JavaScript heruntergerissen. Wer etwas JavaScript und die vielen d.ebi, d.ac, d.ce und d.ctn irritiert - das sind Abkürzungen für häufig verwendete Befehle, die ich in common.js definiert habe: <source lang="javascript"> var d = { d : document, w : window, ebi : function(i) { return document.getElementById(i); }, ebn : function(n) { return document.getElementsByName(n); }, febn : function(n) { return document.getElementsByName(n)[0]; }, ce : function(n) { return document.createElement(n); }, ctn : function(n) { return document.createTextNode(n); }, ac : function(p, c) { return p.appendChild(c); }, ac1 : function(p, c) { p.appendChild(c); return p; } } </source> d.ebi steht zum Beispiel für '''d'''ocument.get'''E'''lement'''B'''y'''I'''d d.ac für '''d'''ocument.'''a'''ppend'''C'''hild usw... In diesem Sinne auch eine Entschuldigung an alle, die bei dem Klammer-Massaker einen Knoten im Hirn bekommen ;-) Dadurch, dass nahezu alles in JavaScript gemacht wird, ist der HTML-Body gähnend leer. Erst beim Laden wird der Seite Leben eingehaucht: <gallery> Datei:raspberry_io_gui.png|Benutzerinterface </gallery> Der Code erzeugt zunächst eine Tabelle, die dann durch Objekte von GpioPin gefüllt wird. Durch Klick auf die span-Elemente bzw. Bilder wird der Inhalt umgeschaltet und per XmlHttpRequest ein Kommando an den Server geschickt. Beim Klick auf Lesen wird ebenfalls per XmlHttpRequest eine Anfrage an den Server gesendet, wie oben erwähnt, mit einem JSON-String antwortet. Dies sieht dann z. B. wie folgt aus: <pre> [{"bit":17,"val":0,"dir":"o"},{"bit":18,"val":1,"dir":"o"},{"bit":21,"val":0,"dir":"o"},{"bit":22,"val":0,"dir":"i"},{"bit":23,"val":1,"dir":"i"},{"bit":24,"val":0,"dir":"o"},{"bit":25,"val":0,"dir":"o"}] </pre> Aufgedröselt wird die Struktur deutlicher: <source lang="javascript"> [ { "bit" : 17, "val" : 0, "dir" : "o" },{ "bit" : 18, "val" : 1, "dir" : "o" },{ "bit" : 21, "val" : 0, "dir" : "o" },{ ... } ] </source> Diese wird durch den JSON-parser in ein Objekt umgewandelt, per Schleife zugeordnet und durch die Funktion GpioPin::SetVals() gesetzt. Die Richtung und Wert kann man einfach durch Klick auf das jeweilige Element verändern. Durch einen Klick auf "Refresh" kann man die tatsächlichen Werte vom Server ermitteln, nach dem Aktivieren der Checkbox geschieht dies automatisch im Sekundentakt. Getestet wurde die die Anwendung bis jetzt im Firefox, "Standard" Android-Browser und dem aktuellen IE, wobei in letzterem die Aktualisierung nicht richtig funktioniert. <gallery> Datei:Raspberry_io_android.jpg|Raspberry Pi mit Tablet </gallery> =Download= [[Datei:Raspberry Pi IO.zip]] ==Hinweise== Der Inhalt der ZIP-Datei kann relativ einfach mit FileZilla auf den Raspberry (per SSH-Filetransfer) geschoben werden. Der Order IO muss unter /var/www/ liegen, gpio.sh an einem nahezu beliebigen Ort. Vor dem Ausführen der gpio.sh nicht vergessen, die Ausführungsrechte zu setzen! [[Kategorie:PC]] [[Kategorie:Raspberry Pi]] 982a39f551cabf79a0c296b69fb2784b8b15a812 Datei:Halbleiter-Formelsammlung.pdf 6 335 830 2013-01-16T07:59:16Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Halbleiterelektronik-Formelsammlung 0 336 831 2013-01-16T07:59:51Z Chris 2 Seite erstellt wikitext text/x-wiki Neben der [[Physik-Formelsammlung]] habe ich während dem Studium auch eine Sammlung vieler wichtiger Formeln in der Halbleiterelektronik geschrieben, die mich gut durch die Klausur brachte ;-). Sie beinhaltet alles rund um die Ersatzschaltbilder von Bipolar- und FET-Transistoren sowie deren Grundschaltungen. Die eingebundenen Stromlaufpläne stammen aus dem Vorlesungsskript von Herrn Prof. Dipl.-Phys. Forster (Hochschule Ulm), der sie mir für die Formelsammlung freundlicherweise zur Verfügung gestellt hat. Wie immer erhebe ich keinen Anspruch auf Vollständigkeit und Korrektheit. Wer Fehler findet oder Ergänzungen beisteuern will, kann sich gerne an [[Benutzer:Chris|mich]] wenden =Inhalt= # Halbleiterdioden ## Großsignalmodell ### Diodenkennlinie ### Temperaturabhängigkeit Diodenkennlinie ### Dioden-Durchbruch ### Speicherzeit pn-Diode ## Kleinsignalmodell ## Diodentypen & Anwendungen ### Z-Diode ### Gleichrichter ### Fotodiode # Bipolar-Transistor ## Ebers-Moll-Modell ### Aktiver Vorwärtsbetrieb ## Kleinsignalmodell Bipolartransistor ### Kleinsignal-Stromverstärkung ### Kollektor-Basis-Rückwirkungswiderstand ## Bipolartransistor als Schalter # Feldeffekt-Transistoren ## Gleichstrommodell MOSFETs ### Stromloser Zustand ### Linearer Bereich (Triodenbereich) ### Abschnürbereich (Sättigungsbereich) ### Vereinfachtes Modell für Handanalyse ## Kleinsignalmodell MOSFETs ## MOSFET als Schalter # Elementare Verstärkerschaltungen ## Grundschaltungen mit Bipolartransistoren ### Emitterschaltung ### Emitterschaltung mit Wechselstrom-Gegenkopplung ### Basisschaltung ### Kollektorschaltung ## Grundschaltung mit FETs ### Source-Schaltung ### Gate-Schaltung ### Drain-Schaltung ## Arbeitspunktstabilisierung ### Arbeitspunkteinstellung ## RC-gekoppelte Verstärker # Aktive Zwei-Transistor-Schaltungen ## Darlington-Schaltung ### Verbund-Darlington-Schaltung ## Kaskode-Schaltung ## IGBT =Download= [[Datei:Halbleiter-Formelsammlung.pdf]] (Stand: 16.01.2013) [[Kategorie:Sonstiges]] fe1c93824b4a9938d0e15809e85043250cab1d0a Halbleiterelektronik-Formelsammlung 0 336 832 831 2013-01-16T08:05:18Z Chris 2 wikitext text/x-wiki Neben der [[Physik-Formelsammlung]] habe ich während dem Studium auch eine Sammlung vieler wichtiger Formeln in der Halbleiterelektronik geschrieben, die mich gut durch die Klausur brachte ;-). Sie beinhaltet alles rund um die Ersatzschaltbilder von Bipolar- und FET-Transistoren sowie deren Grundschaltungen. Die eingebundenen Ersatzschaltbilder und Stromlaufpläne stammen aus dem Vorlesungsskript von Herrn Prof. Dipl.-Phys. Forster (Hochschule Ulm), der sie mir für die Formelsammlung freundlicherweise zur Verfügung gestellt hat. Wie immer erhebe ich keinen Anspruch auf Vollständigkeit und Korrektheit. Wer Fehler findet oder Ergänzungen beisteuern will, kann sich gerne an [[Benutzer:Chris|mich]] wenden. Wichtige Grundformeln sind durch einen dickeren linken Rand der Tabellen hervorgehoben. Die Seitenzahlen am Rand helfen nur, wenn man das Vorlesungsskript vom Frühjahr 2011 hat. =Inhalt= # Halbleiterdioden ## Großsignalmodell ### Diodenkennlinie ### Temperaturabhängigkeit Diodenkennlinie ### Dioden-Durchbruch ### Speicherzeit pn-Diode ## Kleinsignalmodell ## Diodentypen & Anwendungen ### Z-Diode ### Gleichrichter ### Fotodiode # Bipolar-Transistor ## Ebers-Moll-Modell ### Aktiver Vorwärtsbetrieb ## Kleinsignalmodell Bipolartransistor ### Kleinsignal-Stromverstärkung ### Kollektor-Basis-Rückwirkungswiderstand ## Bipolartransistor als Schalter # Feldeffekt-Transistoren ## Gleichstrommodell MOSFETs ### Stromloser Zustand ### Linearer Bereich (Triodenbereich) ### Abschnürbereich (Sättigungsbereich) ### Vereinfachtes Modell für Handanalyse ## Kleinsignalmodell MOSFETs ## MOSFET als Schalter # Elementare Verstärkerschaltungen ## Grundschaltungen mit Bipolartransistoren ### Emitterschaltung ### Emitterschaltung mit Wechselstrom-Gegenkopplung ### Basisschaltung ### Kollektorschaltung ## Grundschaltung mit FETs ### Source-Schaltung ### Gate-Schaltung ### Drain-Schaltung ## Arbeitspunktstabilisierung ### Arbeitspunkteinstellung ## RC-gekoppelte Verstärker # Aktive Zwei-Transistor-Schaltungen ## Darlington-Schaltung ### Verbund-Darlington-Schaltung ## Kaskode-Schaltung ## IGBT =Download= [[Datei:Halbleiter-Formelsammlung.pdf]] (Stand: 27.06.2011) [[Kategorie:Sonstiges]] 87053922719075b895243a82f5f826f11c2458f4 Hauptseite 0 1 833 821 2013-01-16T08:06:14Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *16.01.2013 [[Halbleiter-Formelsammlung]] *11.10.2012 [[EAGLE-Toolbar]] *26.09.2012 [[Sony Dimmer]] *05.05.2012 [[Raspberry Pi IO]] *12.03.2012 [[EMR7370]] *29.12.2011 [[Polizeiauto]] ==Änderungen== *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt 9acc72ade6a9e418d5dc8b0e85d9e84ce163ca04 834 833 2013-01-16T08:06:40Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *16.01.2013 [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 [[EAGLE-Toolbar]] *26.09.2012 [[Sony Dimmer]] *05.05.2012 [[Raspberry Pi IO]] *12.03.2012 [[EMR7370]] *29.12.2011 [[Polizeiauto]] ==Änderungen== *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt 814ce2db09e1cace13b65158915861276417326c 841 834 2013-05-02T19:55:47Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *02.05.2013 [[Farnell-Assistent]] *16.01.2013 [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 [[EAGLE-Toolbar]] *26.09.2012 [[Sony Dimmer]] *05.05.2012 [[Raspberry Pi IO]] *12.03.2012 [[EMR7370]] ==Änderungen== *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt 188d17edc542a3a175263bc0381c4076988c20df 852 841 2013-08-14T15:39:38Z Qsysopr 1 /* Neues */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *14.08.2013 [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 [[Farnell-Assistent]] *16.01.2013 [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 [[EAGLE-Toolbar]] *26.09.2012 [[Sony Dimmer]] *05.05.2012 [[Raspberry Pi IO]] ==Änderungen== *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt 4c604da5f64796a6aea6aca3044244267b2bb2b1 857 852 2013-10-20T08:43:25Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *14.08.2013 [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 [[Farnell-Assistent]] *16.01.2013 [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 [[EAGLE-Toolbar]] *26.09.2012 [[Sony Dimmer]] *05.05.2012 [[Raspberry Pi IO]] ==Änderungen== *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio 4ab8a4eed1098b64b1a4e5ec5ce1010083aca30a 870 857 2013-11-10T16:16:36Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *10.11.2013 [[Zeitraffer mit Linux]] *14.08.2013 [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 [[Farnell-Assistent]] *16.01.2013 [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 [[EAGLE-Toolbar]] *26.09.2012 [[Sony Dimmer]] ==Änderungen== *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio 662e718c4268697c051a03dd1004acbc2eed6a8b 880 870 2014-02-02T21:39:14Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *02.02.2014 [[EAGLE-Bibliotheken]] *10.11.2013 [[Zeitraffer mit Linux]] *14.08.2013 [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 [[Farnell-Assistent]] *16.01.2013 [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 [[EAGLE-Toolbar]] ==Änderungen== *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio 0c36afb5a15c480dfd36aa066132ac5260e47ca2 Datei:Farnell grau.png 6 337 835 2013-05-02T19:41:48Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Farnell-Assistent 0 338 836 2013-05-02T19:44:55Z Chris 2 Die Seite wurde neu angelegt: „Als Student darf und kann man bei [http://de.farnell.com Farnell] bestellt. Sehr praktisch, da es eine sehr große Auswahl gibt und das Zeug auch wirklich schn…“ wikitext text/x-wiki Als Student darf und kann man bei [http://de.farnell.com Farnell] bestellt. Sehr praktisch, da es eine sehr große Auswahl gibt und das Zeug auch wirklich schnell ankommt - auch wenn es etwas etwas teurer als bei anderen Versendern dauert. Eines hat mich am Onlineshop aber immer wieder gestört: In der parametrischen Suche bekommt man alle möglichen Artikel präsentiert, die man als Student nicht unbedingt will, dazu gehören: * Nicht mehr lieferbare Produkte * Bauteile mit Re-Reeling-Service * Produkte aus den USA Der erste Punkt ist unnötig wie ein Kropf, der zweite macht erst Sinn, wenn man eine Pick & Place-Maschine daheim herumstehen hat und letzteres schlägt mit satten 20 Euro Versandkosten zu Buche, was mir in der Eile schon passiert ist (das war dann ein verdammt teurer Widerstand). =Lösung= Ein Problem, das nicht sein muss - es gibt schließlich [https://addons.mozilla.org/de/firefox/addon/greasemonkey/ Greasemonkey], mit dem man Seiten nach dem Laden mit JavaScript verwursten kann. Also habe ich ein kleines Scriptchen geschrieben, das zuerst die Suchergebnisse in ein Array einliest und danach die Produkte, die den Ausschlusskriterien entsprechen, ausgegraut. Die Bedingungen fürs ausgrauen und der "Effekt" selbst kann am unteren Ende des Scripts (nach dem Kommentar "here is where the magic happens") verändert werden: <source lang="js"> for(i = 0; i < articles.length; i++) { var article = articles[i]; if(article.rereel == true || article.stockCount == 0 || article.stockUSA == true) { article.mainrow.style.opacity = 0.2; article.inforow.style.opacity = 0.2; } } </source> In diesem Fall werden alle ge-rereelten, nicht verfügbaren oder aus den USA versendete Bauteile mit 20% (YMMV) Sichtbarkeit dargestellt. Die einzelnen Elemente im Array articles umfassen folgende Informationen: <source lang="js"> article = { "stockUSA" : boolean, //true, wenn es aus den USA kommt "datasheet" : array, //Array aus Links zu PDF-Dateien der Datenblätter "stockCount" : integer, //Verfügbare Menge "rohs" : boolean, //true, wenn RoHS-konform "rereel" : boolean, //true, wenn mit Re-Reeling-Service angeboten "ordercode" : string, //Bestellnummer "mainrow" : HtmlElement, //HTML-Element der Hauptzeile des Artikels "inforow" : HtmlElement //HTML-Element der Zusatzzeile des Artikels }; </source> Die Änderung sieht dann zum Beispiel wie folgt aus: <gallery> Datei:Farnell_grau.png|Ausgeblendet wegen Re-Reeling-Service </gallery> Das ganze hat keinen Anspruch auf Vollständigkeit und Korrektheit, Verbesserungsvorschläge oder Verbesserungen sind jederzeit willkommen. =Download= (kommt gleich) [[Kategorie:PC]] [[Kategorie:Software]] c44e26c010f8ffe213fc95d835613001608c7252 839 836 2013-05-02T19:54:46Z Chris 2 wikitext text/x-wiki Als Student darf und kann man bei [http://de.farnell.com Farnell] bestellt. Sehr praktisch, da es eine sehr große Auswahl gibt und das Zeug auch wirklich schnell ankommt - auch wenn es etwas etwas teurer als bei anderen Versendern dauert. Eines hat mich am Onlineshop aber immer wieder gestört: In der parametrischen Suche bekommt man alle möglichen Artikel präsentiert, die man als Student nicht unbedingt will, dazu gehören: * Nicht mehr lieferbare Produkte * Bauteile mit Re-Reeling-Service * Produkte aus den USA Der erste Punkt ist unnötig wie ein Kropf, der zweite macht erst Sinn, wenn man eine Pick & Place-Maschine daheim herumstehen hat und letzteres schlägt mit satten 20 Euro Versandkosten zu Buche, was mir in der Eile schon passiert ist (das war dann ein verdammt teurer Widerstand). =Lösung= Ein Problem, das nicht sein muss - es gibt schließlich [https://addons.mozilla.org/de/firefox/addon/greasemonkey/ Greasemonkey], mit dem man Seiten nach dem Laden mit JavaScript verwursten kann. Also habe ich ein kleines Scriptchen geschrieben, das zuerst die Suchergebnisse in ein Array einliest und danach die Produkte, die den Ausschlusskriterien entsprechen, ausgegraut. Die Bedingungen fürs ausgrauen und der "Effekt" selbst kann am unteren Ende des Scripts (nach dem Kommentar "here is where the magic happens") verändert werden: <source lang="javascript"> for(i = 0; i < articles.length; i++) { var article = articles[i]; if(article.rereel == true || article.stockCount == 0 || article.stockUSA == true) { article.mainrow.style.opacity = 0.2; article.inforow.style.opacity = 0.2; } } </source> In diesem Fall werden alle ge-rereelten, nicht verfügbaren oder aus den USA versendete Bauteile mit 20% (YMMV) Sichtbarkeit dargestellt. Die einzelnen Elemente im Array articles umfassen folgende Informationen: <source lang="javascript"> article = { "stockUSA" : boolean, //true, wenn es aus den USA kommt "datasheet" : array, //Array aus Links zu PDF-Dateien der Datenblätter "stockCount" : integer, //Verfügbare Menge "rohs" : boolean, //true, wenn RoHS-konform "rereel" : boolean, //true, wenn mit Re-Reeling-Service angeboten "ordercode" : string, //Bestellnummer "mainrow" : HtmlElement, //HTML-Element der Hauptzeile des Artikels "inforow" : HtmlElement //HTML-Element der Zusatzzeile des Artikels }; </source> Die Änderung sieht dann zum Beispiel wie folgt aus: <gallery> Datei:Farnell_grau.png|Ausgeblendet wegen Re-Reeling-Service </gallery> Das ganze hat keinen Anspruch auf Vollständigkeit und Korrektheit, Verbesserungsvorschläge oder Verbesserungen sind jederzeit willkommen. =Download= [[Datei:Farnell_Produkte_ausgrauen.user.js]] [[Kategorie:PC]] [[Kategorie:Software]] aa27cc4152070159197ca1002bac4600f83ec2e8 840 839 2013-05-02T19:55:20Z Chris 2 Kategorie wikitext text/x-wiki Als Student darf und kann man bei [http://de.farnell.com Farnell] bestellt. Sehr praktisch, da es eine sehr große Auswahl gibt und das Zeug auch wirklich schnell ankommt - auch wenn es etwas etwas teurer als bei anderen Versendern dauert. Eines hat mich am Onlineshop aber immer wieder gestört: In der parametrischen Suche bekommt man alle möglichen Artikel präsentiert, die man als Student nicht unbedingt will, dazu gehören: * Nicht mehr lieferbare Produkte * Bauteile mit Re-Reeling-Service * Produkte aus den USA Der erste Punkt ist unnötig wie ein Kropf, der zweite macht erst Sinn, wenn man eine Pick & Place-Maschine daheim herumstehen hat und letzteres schlägt mit satten 20 Euro Versandkosten zu Buche, was mir in der Eile schon passiert ist (das war dann ein verdammt teurer Widerstand). =Lösung= Ein Problem, das nicht sein muss - es gibt schließlich [https://addons.mozilla.org/de/firefox/addon/greasemonkey/ Greasemonkey], mit dem man Seiten nach dem Laden mit JavaScript verwursten kann. Also habe ich ein kleines Scriptchen geschrieben, das zuerst die Suchergebnisse in ein Array einliest und danach die Produkte, die den Ausschlusskriterien entsprechen, ausgegraut. Die Bedingungen fürs ausgrauen und der "Effekt" selbst kann am unteren Ende des Scripts (nach dem Kommentar "here is where the magic happens") verändert werden: <source lang="javascript"> for(i = 0; i < articles.length; i++) { var article = articles[i]; if(article.rereel == true || article.stockCount == 0 || article.stockUSA == true) { article.mainrow.style.opacity = 0.2; article.inforow.style.opacity = 0.2; } } </source> In diesem Fall werden alle ge-rereelten, nicht verfügbaren oder aus den USA versendete Bauteile mit 20% (YMMV) Sichtbarkeit dargestellt. Die einzelnen Elemente im Array articles umfassen folgende Informationen: <source lang="javascript"> article = { "stockUSA" : boolean, //true, wenn es aus den USA kommt "datasheet" : array, //Array aus Links zu PDF-Dateien der Datenblätter "stockCount" : integer, //Verfügbare Menge "rohs" : boolean, //true, wenn RoHS-konform "rereel" : boolean, //true, wenn mit Re-Reeling-Service angeboten "ordercode" : string, //Bestellnummer "mainrow" : HtmlElement, //HTML-Element der Hauptzeile des Artikels "inforow" : HtmlElement //HTML-Element der Zusatzzeile des Artikels }; </source> Die Änderung sieht dann zum Beispiel wie folgt aus: <gallery> Datei:Farnell_grau.png|Ausgeblendet wegen Re-Reeling-Service </gallery> Das ganze hat keinen Anspruch auf Vollständigkeit und Korrektheit, Verbesserungsvorschläge oder Verbesserungen sind jederzeit willkommen. =Download= [[Datei:Farnell_Produkte_ausgrauen.user.js]] [[Kategorie:PC]] [[Kategorie:Software]] [[Kategorie:kleine Helferlein]] 50852090f8526f232bfca8358b11ecf899c90e1c Datei:Farnell Produkte ausgrauen.user.js 6 339 837 2013-05-02T19:53:24Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 838 837 2013-05-02T19:54:10Z Chris 2 lud eine neue Version von „[[Datei:Farnell Produkte ausgrauen.user.js]]“ hoch: UTF8-Encoding wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 EAGLE-Toolbar 0 333 842 820 2013-05-02T19:56:04Z Chris 2 wikitext text/x-wiki Obwohl ich EAGLE sehr gerne mag, hat mich eines schon immer genervt: für jedes Bauteil muss man entweder im Control Panel suchen oder den ungefähren Namen wissen, um es über die Kommandozeile und ADD-Befehl hinzuzufügen. In den altbekannten Trash-Werbesendungen heißt es an dieser Stelle immer "[http://www.youtube.com/results?search_query=wunderharke+5000 Gibt's denn keine bessere Lösung?]" "Doch, jetzt gibt es eine." =Grundlage= EAGLE bietet ein Textmenü an, das sich seit einigen Versionen kaskadieren und sogar bebildern lässt. Die Definition dieser Menüs findet über den Befehl MENU statt. Dieser ist allerdings nicht persistent und nach einem Neustart von EAGLE findet man wieder das "alte" vor. Die beim Start von EAGLE festgelegten Menüs sind in der Startup-Datei eagle.scr im Verzeichnis /scr/ definiert. Diese kann man nach belieben anpassen und somit die am häufigsten verwendeten Befehle schnell zugänglich machen. =Anpassungen= ==Schematic-Editor== Die erste Anpassung fand im Schematic-Editor statt. Dort wurden in das Menü alle meine Standard-Bauteile hinzugefügt - zunächst als grundlegende Texteinträge. Nachdem das Zeug etwas gewachsen ist, beschloss ich, die Verknüpfungen etwas auszuweiten und die Bauteile in Untermenüs zu verlagern. Der Button für die einzelnen Menüs wird durch ein entsprechendes Bildchen verschönert: [[Datei:eagle_toolbar_sch.png]] Neben den Bauteilen lassen sich auch die Standard-Spannungs-Signale sowie ein SMD-Testpad (noch erweiterungsfähig) hinzugefügt werden. Mit dem letzten Button kann ein Screenshot mit 150dpi erstellt werden. ==Board-Editor== Hier fällt das Menü etwas spartaner aus. In der ersten "Funktionsgruppe" lässt sich das Grid in drei Stufen verändern: * Grob: 1,27mm (alternativ 0,635mm) * Mittel: 0,635mm (alternativ 0,3175mm) * Fein: 0,3175mm (alternativ 0,15875mm) Die Maße sind ganz klar auf das Routen von SMD-Bauteilen ausgerichtet und jeweils ein vielfaches von der MIL-Einheit. Mit den nächsten Buttons lassen sich die Top- und Bottom-Layer ein- und ausblenden Die Layer *Names und *Values bleiben davon unangetastet. Das liegt hauptsächlich daran, dass ich diese für das Routing selbst in aller Regel deaktiviere. Bei Bedarf können diese aber einfach in der Script-Datei hinzugefügt werden. Neben den Layern kann auch die Anzeige von Polygonen (wie z. B. Masseflächen umgeschaltet werden. Leider ist der Klick auf den Ausblenden-Buttons nur die halbe Miete: EAGLE rendert die Ansicht leider nicht neu und die Polygone müssen mit dem Ripup-Befehl zurückgesetzt werden. Einen Workaround hierfür habe ich noch nicht gefunden. Zu guter letzt lässt sich über die Toolbar noch das ULP "length-freq-ri.ulp" aufrufen, die gerade bei ein wenig kritischen Designs sehr nützlich ist. =Installation= Wenn man keine eigenen Anpassungen in EAGLE hat und mit meinen Einstellungen leben kann (Grid wird im Layout-Editor im 1,27mm Raster als Punkte dargestellt) kann man die Ordner in der ZIP-Datei direkt ins EAGLE-Verzeichnis werfen. Wer eigene Anpassungen in der scr-Datei hat, kann den /bin/-Ordner zunächst ohne Gefahr kopieren. Die eagle.scr-Dateien müssen jeweils mit einem Text-Editor geöffnet werden und manuell der Bereich zwischen den Kommentaren <pre> ### hobbyelektronik.org EAGLE-Toolbar ### </pre> in die eigene Datei (natürlich an die passende Stelle) kopiert werden. Achtung: Design-Link ist in "meiner" eagle.scr deaktiviert, da diese die zusätzlichen Buttons "aufbläht". Getestet wurde die Toolbar bis jetzt mit EAGLE 5.12.0 und 6.2.0 und wird vermutlich auch mit anderen Versionen funktionieren. =Download= [[Datei:Eagle_toolbar.zip]] [[Kategorie:Sonstiges]] [[Kategorie:Sofware]] [[Kategorie:Kleine Helferlein]] 751890d8d911489cafdb2b470629fc8debd50653 879 842 2014-02-02T21:37:56Z Chris 2 wikitext text/x-wiki Obwohl ich EAGLE sehr gerne mag, hat mich eines schon immer genervt: für jedes Bauteil muss man entweder im Control Panel suchen oder den ungefähren Namen wissen, um es über die Kommandozeile und ADD-Befehl hinzuzufügen. In den altbekannten Trash-Werbesendungen heißt es an dieser Stelle immer "[http://www.youtube.com/results?search_query=wunderharke+5000 Gibt's denn keine bessere Lösung?]" "Doch, jetzt gibt es eine." =Grundlage= EAGLE bietet ein Textmenü an, das sich seit einigen Versionen kaskadieren und sogar bebildern lässt. Die Definition dieser Menüs findet über den Befehl MENU statt. Dieser ist allerdings nicht persistent und nach einem Neustart von EAGLE findet man wieder das "alte" vor. Die beim Start von EAGLE festgelegten Menüs sind in der Startup-Datei eagle.scr im Verzeichnis /scr/ definiert. Diese kann man nach belieben anpassen und somit die am häufigsten verwendeten Befehle schnell zugänglich machen. =Anpassungen= ==Schematic-Editor== Die erste Anpassung fand im Schematic-Editor statt. Dort wurden in das Menü alle meine Standard-Bauteile hinzugefügt - zunächst als grundlegende Texteinträge. Nachdem das Zeug etwas gewachsen ist, beschloss ich, die Verknüpfungen etwas auszuweiten und die Bauteile in Untermenüs zu verlagern. Der Button für die einzelnen Menüs wird durch ein entsprechendes Bildchen verschönert: [[Datei:eagle_toolbar_sch.png]] Neben den Bauteilen lassen sich auch die Standard-Spannungs-Signale sowie ein SMD-Testpad (noch erweiterungsfähig) hinzugefügt werden. Mit dem letzten Button kann ein Screenshot mit 150dpi erstellt werden. ==Board-Editor== Hier fällt das Menü etwas spartaner aus. In der ersten "Funktionsgruppe" lässt sich das Grid in drei Stufen verändern: * Grob: 1,27mm (alternativ 0,635mm) * Mittel: 0,635mm (alternativ 0,3175mm) * Fein: 0,3175mm (alternativ 0,15875mm) Die Maße sind ganz klar auf das Routen von SMD-Bauteilen ausgerichtet und jeweils ein vielfaches von der MIL-Einheit. Mit den nächsten Buttons lassen sich die Top- und Bottom-Layer ein- und ausblenden Die Layer *Names und *Values bleiben davon unangetastet. Das liegt hauptsächlich daran, dass ich diese für das Routing selbst in aller Regel deaktiviere. Bei Bedarf können diese aber einfach in der Script-Datei hinzugefügt werden. Neben den Layern kann auch die Anzeige von Polygonen (wie z. B. Masseflächen umgeschaltet werden. Leider ist der Klick auf den Ausblenden-Buttons nur die halbe Miete: EAGLE rendert die Ansicht leider nicht neu und die Polygone müssen mit dem Ripup-Befehl zurückgesetzt werden. Einen Workaround hierfür habe ich noch nicht gefunden. Zu guter letzt lässt sich über die Toolbar noch das ULP "length-freq-ri.ulp" aufrufen, die gerade bei ein wenig kritischen Designs sehr nützlich ist. =Installation= Wenn man keine eigenen Anpassungen in EAGLE hat und mit meinen Einstellungen leben kann (Grid wird im Layout-Editor im 1,27mm Raster als Punkte dargestellt) kann man die Ordner in der ZIP-Datei direkt ins EAGLE-Verzeichnis werfen. Wer eigene Anpassungen in der scr-Datei hat, kann den /bin/-Ordner zunächst ohne Gefahr kopieren. Die eagle.scr-Dateien müssen jeweils mit einem Text-Editor geöffnet werden und manuell der Bereich zwischen den Kommentaren <pre> ### hobbyelektronik.org EAGLE-Toolbar ### </pre> in die eigene Datei (natürlich an die passende Stelle) kopiert werden. Achtung: Design-Link ist in "meiner" eagle.scr deaktiviert, da diese die zusätzlichen Buttons "aufbläht". Getestet wurde die Toolbar bis jetzt mit EAGLE 5.12.0 und 6.2.0 und wird vermutlich auch mit anderen Versionen funktionieren. =Download= [[Datei:Eagle_toolbar.zip]] [[Kategorie:Sonstiges]] [[Kategorie:Sofware]] [[Kategorie:Kleine Helferlein]] [[Kategorie:EAGLE]] a87ababd83711a4289dadefc795ff80b45251fea ASCII-Tabelle 0 214 843 585 2013-05-02T19:56:51Z Chris 2 wikitext text/x-wiki [[Bild:Ascii-Tabelle Ausschnitt.png|thumb|Ausschnitt aus der ASCII-Tabelle]] Beim Programmieren ist der Besitz einer [[wpde:ASCII-Tabelle|ASCII-Tabelle]] oft sehr praktisch. Nur leider habe ich bis noch keine gefunden, die das bietet, was ich will. Deshalb habe ich die Textverarbeitung aktiviert und mich daran gemacht, eine eigene ASCII-Tabelle zu entwerfen. Die Tabelle umfasst zwei Seiten. Wer nur den "normalen" Zeichensatz benötigt, druckt die erste Seite, wer den erweiterten Satz möchte, druckt sich entsprechend beide. Rund um die Tabelle sind die Binäranteile jeder Teile und Spalte abgedruckt, sodass man vom Binärcode relativ schnell zum Zeichen finden kann. In den Kästchen selbst findet sich zum einen das Zeichen selbst, die binäre und darunter die dezimale (links) und hexadezimale (rechts) Entsprechung. Da man die Steuerzeichen auf Papier direkt nicht richtig abbilden kann, sind die Ensprechungen in Kurzform abgedruckt. Zusätzlich befindet sich darunter (sofern vorhanden) die aus Kommandozeilen bekannte Caret-Notation sowie die Escape-Codes aus C-oiden Sprachen. =Download= [[Datei:ASCII-Tabelle.pdf]] [[Category:Sonstiges]] [[Kategorie:Kleine Helferlein]] 9d69f2b1bc780b820c7a16caf8ef22ed5bf7ab59 Datei:Belkin F8J056 offen.jpg 6 340 844 2013-08-14T14:54:35Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Belkin F8J056 pcb bot.jpg 6 341 845 2013-08-14T14:59:24Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Belkin F8J056 pcb top.jpg 6 342 846 2013-08-14T14:59:26Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Belkin F8J056 pcb bot2.jpg 6 343 847 2013-08-14T15:07:29Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Belkin F8J056 umgebaut.jpg 6 344 848 2013-08-14T15:25:28Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Umbau Belkin Auto-USB-Lader 0 345 849 2013-08-14T15:34:56Z Chris 2 Die Seite wurde neu angelegt: „Meine Schwester braucht Strom fürs Handy im Auto und da es beim Mobilfunkanbieter mit dem roten Tropfen einen entsprechenden Adapter für 5 Euro gab, hat sie …“ wikitext text/x-wiki Meine Schwester braucht Strom fürs Handy im Auto und da es beim Mobilfunkanbieter mit dem roten Tropfen einen entsprechenden Adapter für 5 Euro gab, hat sie auch gleich zugeschlagen. Das Teil nennt sich "Belkin Micro USB Car Charger inkl. 30-Pin Sync-/Ladekabel" und hat die Produkt-Nummer F8J056. Einen kleinen Nachteil hat das Ding allerdings: "Designed for products with half-eaten fruits". Natürlich funktioniert es auch mit anderen Geräten, dann aber nur innerhalb (trotzdem nicht ganz eingehaltenen) USB-Spezifikation - also 500 mA. Besonders wenn man rechenlastige Dinge wie Navigation macht, kann da die Luft dünn werden. =Die Theorie= Um gut mit Android-Geräten zu funktionieren muss der Adapter umgebaut werden. Bei dem Apple-Zeug müssen die USB-Datenleitungen D+ und D- über Spannungsteiler auf ca. VBus/2=2,5 V gebracht werden, wobei meines Wissens auch der Strom (und damit die Widerstandswerte) definiert sind. Bei Androiden müssen üblicherweise D+ und D- miteinander verbunden werden. Das könnte man auch mit einem Zwischenstecker oder umgebauten USB-Kabel machen, aber das ist langweilig und kann jeder. =Auf die Dose!= Hier beginnt auch schon das Problem: Das Gehäuse ist ziemlich gut verschlossen. Zwischen den Massefedern außen sieht man allerdings eine feine Naht, die einen Angriffspunkt darstellt. [[Datei:Belkin_F8J056_offen.jpg|thumb|Geöffneter Ladeadapter]] Mit einem großen flachen Schraubendreher lassen sich die Gehäusehälften auch etwas auseinanderbiegen, mit sehr viel sanfter Gewalt kann man sich mit einem zweiten (feinen) Schraubendreher an der kompletten Kante entlang arbeiten. Am besten, man klemmt den Adapter in einen Schraubstock ein. Ich habe dabei ([http://hobbyelektronik.org/b/2011/08/stigmata/ mal wieder]) die Erfahrung gemacht, dass sich die Spitze von Schraubendrehern und Handinnenflächen nicht unbedingt vertragen (nach knapp 14 Tagen ist es immerhin wieder fast verheilt). Auf jeden Fall war das Teil damit auch geöffnet Die Leiterplatte bekommt man am besten heraus, indem man ein USB-Kabel einsteckt, und vorsichtig (!) hebelt. Zum Vorschein kommt folgendes Platinchen: <gallery> Datei:Belkin_F8J056_pcb_top.jpg|Leiterplatte von oben Datei:Belkin_F8J056_pcb_bot.jpg|Leiterplatte von unten </gallery> Sieht auf den ersten Blick gar nicht mal so übel aus. Nicht dieses Standard-biestige-MC34063-Design, sogar eine Polyfuse und Verpolungsschutz am Eingang wurden spendiert. Der Schaltwandler selbst (etwas anderes kann man sich aufgrund der relativ großen Induktivität, der dicken Diode und vor allem der ordentlichen 2 A am Ausgang nicht vorstellen) sitzt unter dem großen Masseblech und ermöglicht zusätzliche Wärmeabführung. Also auch mechanisch ganz nett designed. Wie dem auch sei, nachdem auf der Oberseite keine Widerstände zu sehen sind, müssen sich diese unterm Blech befinden, also weg damit: <gallery> Datei:Belkin_F8J056_pcb_bot2.jpg|Leiterplatte von unten, ohne Blech </gallery> =Umbau= Zum Vorschein kommt ein NT3875A von Noveltek, der laut Datenblatt genau für diesen Zweck gemacht ist. Unter der USB-Buchse befinden sich auch ein paar Widerstände, die mit den Datenleitungen verbunden sind. In der Schaltung gemessen ergibt sich: <math>R7 = \infty; R8 = 33,4 \textrm{ k}\Omega; R9 = 24,25 \textrm{ k}\Omega; R11 = 24,5 \textrm{ k}\Omega; R10 = 31,35 \textrm{ k}\Omega</math> Das Auslöten zeigt: Wer misst, misst mist und natürlich: Niemals im eingebauten Zustand messen! Denn tatsächlich verhalten sich die Widerstände wie folgt: <math>R7 = \infty; R8 = 75,2 \textrm{ k}\Omega; R9 = 43,1 \textrm{ k}\Omega; R11 = 50 \textrm{ k}\Omega; R10 = 50 \textrm{ k}\Omega</math> Im Endeffekt egal, denn sie kommen eh weg. Um D+ und D- zu verbinden, kann entweder R7 oder die oberen Pads von R8 und R9 gebrückt werden. Da die unter dem USB-Port liegende LED deutlich blendet, wurde deren Vorwiderstand (R6) gleich durch einen etwas größeren (4,7 k) ersetzt. Weil ich nix in 0402 bzw. 0603 da hatte, musste dann halt ein querliegender Widerstand in der Baugröße 0805 herhalten: <gallery> Datei:Belkin_F8J056_umgebaut.jpg|Neuer Widerstand für die LED </gallery> Ans Handy geklemmt zieht das Teil bei 12 V Eingangsspannung 0,42 A, also gehen 5W (bei meinem etwas älteren HTC) in den Akku. Passt. =Zusammenbau= Der Zusammenbau ist relativ einfach - Metallbügel anlöten, im Gehäuse versenken und dieses verschließen. Hier reicht stecken alleine nicht, es will geklebt werden. Mit 2-Komponenten-Kleber eine sichere Sache: Einmal an der Rundung entlang, etwas an den Gehäusekanten dran (nicht zu viel!) und an der "Spitze" sehr vorsichtig agieren! Läuft die Brühe bis zum [http://hamburgforbeginners.wordpress.com/2008/10/13/pinopel/ Pinöpel] vorne, kann es zu Kontaktproblemen kommen. Mir ist es natürlich passiert - durch Drehen und vorsichtiges Drücken kann man ihn wieder frei bekommen. Besser ist es aber, es gar nicht so weit kommen zu lassen. [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] 5c3dbfad4736bfd4b84d798ef688474f77352bdf 850 849 2013-08-14T15:36:36Z Chris 2 /* Auf die Dose! */ wikitext text/x-wiki Meine Schwester braucht Strom fürs Handy im Auto und da es beim Mobilfunkanbieter mit dem roten Tropfen einen entsprechenden Adapter für 5 Euro gab, hat sie auch gleich zugeschlagen. Das Teil nennt sich "Belkin Micro USB Car Charger inkl. 30-Pin Sync-/Ladekabel" und hat die Produkt-Nummer F8J056. Einen kleinen Nachteil hat das Ding allerdings: "Designed for products with half-eaten fruits". Natürlich funktioniert es auch mit anderen Geräten, dann aber nur innerhalb (trotzdem nicht ganz eingehaltenen) USB-Spezifikation - also 500 mA. Besonders wenn man rechenlastige Dinge wie Navigation macht, kann da die Luft dünn werden. =Die Theorie= Um gut mit Android-Geräten zu funktionieren muss der Adapter umgebaut werden. Bei dem Apple-Zeug müssen die USB-Datenleitungen D+ und D- über Spannungsteiler auf ca. VBus/2=2,5 V gebracht werden, wobei meines Wissens auch der Strom (und damit die Widerstandswerte) definiert sind. Bei Androiden müssen üblicherweise D+ und D- miteinander verbunden werden. Das könnte man auch mit einem Zwischenstecker oder umgebauten USB-Kabel machen, aber das ist langweilig und kann jeder. =Auf die Dose!= [[Datei:Belkin_F8J056_offen.jpg|thumb|Geöffneter Ladeadapter]] Hier beginnt auch schon das Problem: Das Gehäuse ist ziemlich gut verschlossen. Zwischen den Massefedern außen sieht man allerdings eine feine Naht, die einen Angriffspunkt darstellt. Mit einem großen flachen Schraubendreher lassen sich die Gehäusehälften bei den Federn auch etwas auseinander biegen, mit sehr viel sanfter Gewalt kann man sich mit einem zweiten (feinen) Schraubendreher an der kompletten Kante entlang arbeiten. Am besten, man klemmt den Adapter in einen Schraubstock ein. Ich habe dabei ([http://hobbyelektronik.org/b/2011/08/stigmata/ mal wieder]) die Erfahrung gemacht, dass sich die Spitze von Schraubendrehern und Handinnenflächen nicht unbedingt vertragen (nach knapp 14 Tagen ist es immerhin wieder fast verheilt). Auf jeden Fall war das Teil damit auch geöffnet Die Leiterplatte bekommt man am besten heraus, indem man ein USB-Kabel einsteckt, und vorsichtig (!) hebelt. Zum Vorschein kommt folgendes Platinchen: <gallery> Datei:Belkin_F8J056_pcb_top.jpg|Leiterplatte von oben Datei:Belkin_F8J056_pcb_bot.jpg|Leiterplatte von unten </gallery> Sieht auf den ersten Blick gar nicht mal so übel aus. Nicht dieses Standard-biestige-MC34063-Design, sogar eine Polyfuse und Verpolungsschutz am Eingang wurden spendiert. Der Schaltwandler selbst (etwas anderes kann man sich aufgrund der relativ großen Induktivität, der dicken Diode und vor allem der ordentlichen 2 A am Ausgang nicht vorstellen) sitzt unter dem großen Masseblech und ermöglicht zusätzliche Wärmeabführung. Also auch mechanisch ganz nett designed. Wie dem auch sei, nachdem auf der Oberseite keine Widerstände zu sehen sind, müssen sich diese unterm Blech befinden, also weg damit: <gallery> Datei:Belkin_F8J056_pcb_bot2.jpg|Leiterplatte von unten, ohne Blech </gallery> =Umbau= Zum Vorschein kommt ein NT3875A von Noveltek, der laut Datenblatt genau für diesen Zweck gemacht ist. Unter der USB-Buchse befinden sich auch ein paar Widerstände, die mit den Datenleitungen verbunden sind. In der Schaltung gemessen ergibt sich: <math>R7 = \infty; R8 = 33,4 \textrm{ k}\Omega; R9 = 24,25 \textrm{ k}\Omega; R11 = 24,5 \textrm{ k}\Omega; R10 = 31,35 \textrm{ k}\Omega</math> Das Auslöten zeigt: Wer misst, misst mist und natürlich: Niemals im eingebauten Zustand messen! Denn tatsächlich verhalten sich die Widerstände wie folgt: <math>R7 = \infty; R8 = 75,2 \textrm{ k}\Omega; R9 = 43,1 \textrm{ k}\Omega; R11 = 50 \textrm{ k}\Omega; R10 = 50 \textrm{ k}\Omega</math> Im Endeffekt egal, denn sie kommen eh weg. Um D+ und D- zu verbinden, kann entweder R7 oder die oberen Pads von R8 und R9 gebrückt werden. Da die unter dem USB-Port liegende LED deutlich blendet, wurde deren Vorwiderstand (R6) gleich durch einen etwas größeren (4,7 k) ersetzt. Weil ich nix in 0402 bzw. 0603 da hatte, musste dann halt ein querliegender Widerstand in der Baugröße 0805 herhalten: <gallery> Datei:Belkin_F8J056_umgebaut.jpg|Neuer Widerstand für die LED </gallery> Ans Handy geklemmt zieht das Teil bei 12 V Eingangsspannung 0,42 A, also gehen 5W (bei meinem etwas älteren HTC) in den Akku. Passt. =Zusammenbau= Der Zusammenbau ist relativ einfach - Metallbügel anlöten, im Gehäuse versenken und dieses verschließen. Hier reicht stecken alleine nicht, es will geklebt werden. Mit 2-Komponenten-Kleber eine sichere Sache: Einmal an der Rundung entlang, etwas an den Gehäusekanten dran (nicht zu viel!) und an der "Spitze" sehr vorsichtig agieren! Läuft die Brühe bis zum [http://hamburgforbeginners.wordpress.com/2008/10/13/pinopel/ Pinöpel] vorne, kann es zu Kontaktproblemen kommen. Mir ist es natürlich passiert - durch Drehen und vorsichtiges Drücken kann man ihn wieder frei bekommen. Besser ist es aber, es gar nicht so weit kommen zu lassen. [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] 89ab5d88c175746bb49a9413ca8d819481ea6893 851 850 2013-08-14T15:38:52Z Qsysopr 1 verschob „[[Umbau Belin Auto-USB-Lader]]“ nach „[[Umbau Belkin Auto-USB-Lader]]“ wikitext text/x-wiki Meine Schwester braucht Strom fürs Handy im Auto und da es beim Mobilfunkanbieter mit dem roten Tropfen einen entsprechenden Adapter für 5 Euro gab, hat sie auch gleich zugeschlagen. Das Teil nennt sich "Belkin Micro USB Car Charger inkl. 30-Pin Sync-/Ladekabel" und hat die Produkt-Nummer F8J056. Einen kleinen Nachteil hat das Ding allerdings: "Designed for products with half-eaten fruits". Natürlich funktioniert es auch mit anderen Geräten, dann aber nur innerhalb (trotzdem nicht ganz eingehaltenen) USB-Spezifikation - also 500 mA. Besonders wenn man rechenlastige Dinge wie Navigation macht, kann da die Luft dünn werden. =Die Theorie= Um gut mit Android-Geräten zu funktionieren muss der Adapter umgebaut werden. Bei dem Apple-Zeug müssen die USB-Datenleitungen D+ und D- über Spannungsteiler auf ca. VBus/2=2,5 V gebracht werden, wobei meines Wissens auch der Strom (und damit die Widerstandswerte) definiert sind. Bei Androiden müssen üblicherweise D+ und D- miteinander verbunden werden. Das könnte man auch mit einem Zwischenstecker oder umgebauten USB-Kabel machen, aber das ist langweilig und kann jeder. =Auf die Dose!= [[Datei:Belkin_F8J056_offen.jpg|thumb|Geöffneter Ladeadapter]] Hier beginnt auch schon das Problem: Das Gehäuse ist ziemlich gut verschlossen. Zwischen den Massefedern außen sieht man allerdings eine feine Naht, die einen Angriffspunkt darstellt. Mit einem großen flachen Schraubendreher lassen sich die Gehäusehälften bei den Federn auch etwas auseinander biegen, mit sehr viel sanfter Gewalt kann man sich mit einem zweiten (feinen) Schraubendreher an der kompletten Kante entlang arbeiten. Am besten, man klemmt den Adapter in einen Schraubstock ein. Ich habe dabei ([http://hobbyelektronik.org/b/2011/08/stigmata/ mal wieder]) die Erfahrung gemacht, dass sich die Spitze von Schraubendrehern und Handinnenflächen nicht unbedingt vertragen (nach knapp 14 Tagen ist es immerhin wieder fast verheilt). Auf jeden Fall war das Teil damit auch geöffnet Die Leiterplatte bekommt man am besten heraus, indem man ein USB-Kabel einsteckt, und vorsichtig (!) hebelt. Zum Vorschein kommt folgendes Platinchen: <gallery> Datei:Belkin_F8J056_pcb_top.jpg|Leiterplatte von oben Datei:Belkin_F8J056_pcb_bot.jpg|Leiterplatte von unten </gallery> Sieht auf den ersten Blick gar nicht mal so übel aus. Nicht dieses Standard-biestige-MC34063-Design, sogar eine Polyfuse und Verpolungsschutz am Eingang wurden spendiert. Der Schaltwandler selbst (etwas anderes kann man sich aufgrund der relativ großen Induktivität, der dicken Diode und vor allem der ordentlichen 2 A am Ausgang nicht vorstellen) sitzt unter dem großen Masseblech und ermöglicht zusätzliche Wärmeabführung. Also auch mechanisch ganz nett designed. Wie dem auch sei, nachdem auf der Oberseite keine Widerstände zu sehen sind, müssen sich diese unterm Blech befinden, also weg damit: <gallery> Datei:Belkin_F8J056_pcb_bot2.jpg|Leiterplatte von unten, ohne Blech </gallery> =Umbau= Zum Vorschein kommt ein NT3875A von Noveltek, der laut Datenblatt genau für diesen Zweck gemacht ist. Unter der USB-Buchse befinden sich auch ein paar Widerstände, die mit den Datenleitungen verbunden sind. In der Schaltung gemessen ergibt sich: <math>R7 = \infty; R8 = 33,4 \textrm{ k}\Omega; R9 = 24,25 \textrm{ k}\Omega; R11 = 24,5 \textrm{ k}\Omega; R10 = 31,35 \textrm{ k}\Omega</math> Das Auslöten zeigt: Wer misst, misst mist und natürlich: Niemals im eingebauten Zustand messen! Denn tatsächlich verhalten sich die Widerstände wie folgt: <math>R7 = \infty; R8 = 75,2 \textrm{ k}\Omega; R9 = 43,1 \textrm{ k}\Omega; R11 = 50 \textrm{ k}\Omega; R10 = 50 \textrm{ k}\Omega</math> Im Endeffekt egal, denn sie kommen eh weg. Um D+ und D- zu verbinden, kann entweder R7 oder die oberen Pads von R8 und R9 gebrückt werden. Da die unter dem USB-Port liegende LED deutlich blendet, wurde deren Vorwiderstand (R6) gleich durch einen etwas größeren (4,7 k) ersetzt. Weil ich nix in 0402 bzw. 0603 da hatte, musste dann halt ein querliegender Widerstand in der Baugröße 0805 herhalten: <gallery> Datei:Belkin_F8J056_umgebaut.jpg|Neuer Widerstand für die LED </gallery> Ans Handy geklemmt zieht das Teil bei 12 V Eingangsspannung 0,42 A, also gehen 5W (bei meinem etwas älteren HTC) in den Akku. Passt. =Zusammenbau= Der Zusammenbau ist relativ einfach - Metallbügel anlöten, im Gehäuse versenken und dieses verschließen. Hier reicht stecken alleine nicht, es will geklebt werden. Mit 2-Komponenten-Kleber eine sichere Sache: Einmal an der Rundung entlang, etwas an den Gehäusekanten dran (nicht zu viel!) und an der "Spitze" sehr vorsichtig agieren! Läuft die Brühe bis zum [http://hamburgforbeginners.wordpress.com/2008/10/13/pinopel/ Pinöpel] vorne, kann es zu Kontaktproblemen kommen. Mir ist es natürlich passiert - durch Drehen und vorsichtiges Drücken kann man ihn wieder frei bekommen. Besser ist es aber, es gar nicht so weit kommen zu lassen. [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] 89ab5d88c175746bb49a9413ca8d819481ea6893 Hobbyelektronik.org:Impressum 4 4 853 68 2013-10-19T13:53:30Z Chris 2 wikitext text/x-wiki == Hauptverantwortlicher<br> == [[Benutzer:Chris|Christof Rueß, B. Eng.]]<br>St.-Wendelin-Str. 9<br>89264 Weißenhorn<br>E-Mail: chris at hobbyelektronik punkt org<br>ICQ: [http://www.icq.com/people/about_me.php?uin=176979879 176979879] == Mitwirkende == [[Benutzer:Robert|Robert Obermayer]]<br>E-Mail: robert at hobbyelektronik punkt org<br>ICQ: [http://www.icq.com/people/about_me.php?uin=78202589 78202589] == Kontakt == Wenn du Fragen an uns hast, lies bitte zuerst nochmal die Seite, zu der du die Frage hast und dann evtl. nochmal die [[FAQ]].<br>Am einfachsten und am unkompliziertesten ist der Kontakt per E-Mail.<br>Um Spams ein bisschen einzuschränken, dürftest du auf der Homepage hier keine klickbaren Links finden. Wie man an die Adresse kommt, muss (so denke ich) nicht erklärt werden. Weiterhin habe wir einen [[#hobbyelektronik|IRC-Channel]], der von uns auch relativ stark genutzt wird und auch internationales Publikum (ok, ein Schwede) hat. Einfach mal vorbeischauen: [irc://irc.quakenet.eu.org/hobbyelektronik #hobbyelektronik @ Quakenet] <br> Bitte beachte auch die Seite [[Hobbyelektronik.org:Über Hobbyelektronik.org|Über Hobbyelektronik.org]], auf der insbesondere der Haftungsausschluss zu beachten ist! fca9751252daead36bef82e1641904d711c0cb80 855 853 2013-10-19T13:58:03Z Chris 2 IRC entfernt wikitext text/x-wiki == Hauptverantwortlicher<br> == [[Benutzer:Chris|Christof Rueß B.Eng.]]<br>St.-Wendelin-Str. 9<br>89264 Weißenhorn<br>E-Mail: chris at hobbyelektronik punkt org<br>ICQ: [http://www.icq.com/people/about_me.php?uin=176979879 176979879] == Mitwirkende == [[Benutzer:Robert|Robert Obermayer]]<br>E-Mail: robert at hobbyelektronik punkt org<br>ICQ: [http://www.icq.com/people/about_me.php?uin=78202589 78202589] == Kontakt == Wenn du Fragen an uns hast, lies bitte zuerst nochmal die Seite, zu der du die Frage hast und dann evtl. nochmal die [[FAQ]].<br>Am einfachsten und am unkompliziertesten ist der Kontakt per E-Mail.<br>Um Spams ein bisschen einzuschränken, dürftest du auf der Homepage hier keine klickbaren Links finden. Wie man an die Adresse kommt, muss (so denke ich) nicht erklärt werden. Bitte beachte auch die Seite [[Hobbyelektronik.org:Über Hobbyelektronik.org|Über Hobbyelektronik.org]], auf der insbesondere der Haftungsausschluss zu beachten ist! 788cacf14009d991d772b4913aa2379ba7e897e8 Benutzer:Chris 2 45 854 824 2013-10-19T13:55:54Z Chris 2 Studium Ade wikitext text/x-wiki = Wie es dazu kam = Irgendwann um 2003 fing ich damit an, meine (mehr oder weniger gelungenen) Bastel-Projekte in HTML zu verwandeln und auf hobby-elektronik.de.vu zu veröffentlichen. Der Speicherplatz bei Tripod wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich irgendwann, auf das schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10 April 2005 die Domain hobbyelektronik.org registriert. Zu .org kam es, da mir eine Woche davor jemand die .net-Domain weggeschnappte. Im Nachhinein bin ich glücklich, dem damaligen .net-Hype entgangen zu sein. Eine richtige Organisation sind wir zwar noch immer nicht aber was nicht ist, kann ja noch werden ;) = Was ich mache = Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" bezeichnen. Von Oktober 2009 bis Juli 2013 habe ich Elektrotechnik/Nachrichtentechnik an der [http://www.hs-ulm.de Hochschule Ulm] studiert und Arbeite seit Oktober 2013 im Automotive-Bereich. Die Schnittmenge bzw. vielmehr die Verbindung aus den beiden Bereichen kommen auch wieder in meinen Hobbys zusammen. Seit September 2012 bin ich Kleinunternehmer und repariere nebenzu Computer, wobei ein weiterer - für Besucher dieser Homepage interessantere - Geschäftsbereich geplant ist. Abseits vom Schreibtisch findet man mich ab und zu hinter der Spiegelreflex, (viel zu selten) auf dem Rad oder in weit entfernten Ländern. Ein paar Eindrücke davon kann man auf den Fehlerseiten dieser Homepage finden. = Warum das Ganze? = Ganz einfach: Weil es mir Spaß macht. Wie an anderer Stelle schon erwähnt, bezeichne ich diese Seite als "nicht-kommerzielles Umfeld". Damit ist gemeint, dass ich mit dieser Homepage kein Geld verdiene (keine Werbung, keine Partnerschaften mir irgendwelchen Firmen, etc.) und es ehrlich gesagt auch nicht will. Das bedeutet auch, dass Produkterwähnungen und evtl. auch Empfehlungen aus meiner eigenen Erfahrung und Meinung gemacht werden. (Wer spenden will - gerne auch Sachspenden - ist natürlich willkommen ;)). Neben dem Spaß geht es mir auch darum, etwas an andere Bastler, Elektronik-Einsteiger und DICH weiter- bzw. zurückzugeben. Auch ich habe mal sehr klein angefangen und war froh um alles, was mich näher in Richtung Computer und Elektronik brachte (und auch heute noch bringt). Wenn man so will, kann man es als Kreislauf verstehen :) [http://sprut.de/misc/hpphilos.htm Sprut] hat es meiner Meinung mit seiner Homepage-Philosophie sehr gut getroffen. = Kannst du mir... = ...bei <Thema hier einsetzen> helfen? Jein. Wenn du ehrliches Interesse hast, helfe ich gerne. Was ich allerdings überhaupt nicht abkann ist die "Mach mal-" bzw. "Freibiermentalität", die manche an den Tag legen. Solche können erst wiederkommen, wenn ich einen Gewerbeschein habe... = Kontakt = Solltest du Fragen, Kritik, Verbesserungsvorschläge oder Fehler auf den Seiten hier gefunden haben - eine kleine Mail genügt und wird gerne beantwortet: chris at hobbyelektronik punkt org Wer mich in sozialen Netzwerken sucht, wird wenig erfolg haben. Will ich nicht, mach ich nicht. (siehe auch [[Hobbyelektronik.org:Impressum|Impressum]]) 3eb142143324e9ddf6b2d487e31247f60e1cfc78 Datei:EMR7370.zip 6 295 856 746 2013-10-20T08:42:13Z Chris 2 lud eine neue Version von „[[Datei:EMR7370.zip]]“ hoch: Tippfehler in main() korrigiert. wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Zeitraffer mit Linux 0 346 858 2013-11-07T22:01:12Z Chris 2 Seite erstellt wikitext text/x-wiki Was macht man mit einem stromsparenden Computer und einer Webcam? Die Frage habe ich mir genau zur letzten Lernphase meines Studiums gestellt und gleich mal auf die Probe gestellt, ob es möglich ist, innerhalb einer Mittagspause eine Zeitraffer-Kamera zu basteln (siehe auch [http://hobbyelektronik.org/b/2013/06/ein-tag/ hier]). Wenn man als Bash-Anfänger die die Dauer der Mittagspause an die südländische Siesta annähert kann ich schon vorweg sagen: Ja, es ist möglich! = Ausgangsmaterial = Als Computer kommt der Raspberry Pi zum Einsatz. Als Webcam dient eine Logitech C310. Um die SD-Karte etwas zu schonen darf ein billiger USB-Stick zum Einsatz, der nur als Aufnahmeziel dient. = Einrichten = == Kamera == Da es sich bei der Webcam um eine mit USB-Anschluss handelt, kann sie (meines Wissens) nicht ausschließlich mit dem verwendet werden, das Raspian hergibt. Mit dem Befehl lsusb kann man herausfinden, was am USB hängt: <pre> $ lsusb Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 058f:6387 Alcor Micro Corp. Flash Drive Bus 001 Device 005: ID 046d:081b Logitech, Inc. Webcam C310 </pre> Die Webcam ist also am Computer anhängig, genauso wie der USB-Stick. Über den Befehl ls /dev/video* werden alle Geräte angezeigt, die mit dem Namen video anfangen. Wurden also Treiber für die Kamera gefunden, erscheint sie in der Ausgabe: <pre> $ ls /dev/video* /dev/video0 </pre> Weil cat /dev/video0 > foo.jpg nicht so wirklich funktioniert, muss ein Vermittler her. Ich habe gute Erfahrungen mit fswebcam gemacht. Installation und Test sehen wie folgt aus: <pre> $ sudo apt-get install fswebcam [...] $ fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 testimg.jpg </pre> Der letztere Befehl nimmt ein Bild mit der Auflösung (Parameter -r) 1280x960 auf. Das -q nach der Qualitätsstufe (hier: 85) ist Absicht - bei dem Parameter handelt es sich nicht um -q wie quality, sondern um quiet. Mit -d wird das Device gewählt und anschließend folgt die Ausgabedatei. Diese kann, sofern ein Webserver installiert ist, nach /var/www verschieben oder natürlich direkt auf dem Computer ansehen. In meinem Fall wird der Raspberry "headless" betrieben und die Datei über SSH-Filetransfer auf den Haupt-PC befördert. Funktioniert die Kamera, kann der USB-Speicher angedockt werden: == USB-Stick einbinden == Viele Wege führen bekanntlich nach Rom, genauso kann man Speicher auf verschiedene Weisen einbinden. Das hier ist eine. Zunächst muss ein Verzeichnis angelegt werden, in das der USB-Stick später eingebunden (gemountet) wird. In meinem Fall ist dies /media/usb: <pre> mkdir /media/usb </pre> Nun muss herausgefunden werden, wie man den Speicher anspricht. Am besten verwendet man dessen [[wpde:Universally Unique Identifier|Universally Unique Identifier]] (kurz UUID). Der Vorteil an diesem ist, wie der Name schon sagt, dass er Eindeutig ist. Mit dem Befehl blkid können die UUIDs aller verfügbaren Speicher angezeigt werden: <pre> $ blkid /dev/sda1: UUID="0CA5-719C" TYPE="vfat" LABEL="KINGSTON" /dev/mmcblk0p1: SEC_TYPE="msdos" UUID="C522-EA52" TYPE="vfat" /dev/mmcblk0p2: UUID="62ba9ec9-47d9-4421-aaee-71dd6c0f3707" TYPE="ext4" </pre> In geistiger Umnachtung habe ich den USB-Stick "KINGSTON" genannt, das hat allerdings keine Bedeutung. Wichtig ist das, was hinter "UUID=" steht. Man kann den Stick zwar schnell mit mount einbinden, nach dem nächsten Neustart hat man ihn aber verloren und das passiert - auch wenn das System stabil läuft - mit Sicherheit. Also muss er in die fstab (file system table) eingetragen werden. Da man mit ihr nicht spielt, muss sie mit Superuser-Rechten bearbeitet werden: <pre> $ sudo nano /etc/fstab </pre> Die bereits vorhandenen Einträge kann man ignorieren, hier muss der zu verwendende USB-Stick hinzugefügt werden. Ist dieser mit FAT formatiert und hat die UUID 0CA5-719C, kann folgende Zeile an das Ende der Datei geschrieben werden: <pre> UUID=0CA5-719C /media/usb/ vfat defaults,auto,users,noatime,umask=000,rw 0 0 </pre> Mit Strg+X Schließen und das Speichern mit Y und Druck auf die Enter-Taste bestätigen. Navigiert man unter /media/usb kann man nun wunderbar Dateien anlegen, ABER: Diese befinden sich NICHT auf dem USB-Stick! fstab wird nur beim Neustart gelesen. Also heißt es <pre> $ sudo reboot </pre> eingeben und somit die Uptime auf 0 zurücksetzen. Mit dem Befehl df kann jetzt überprüft werden, ob der Speicher richtig eingebunden wurde. Gleichzeitig sieht man auch, wie viel Speicher bereits genutzt wird: <pre> $ df Filesystem 1K-blocks Used Available Use% Mounted on rootfs 1838936 1775400 0 100% / /dev/root 1838936 1775400 0 100% / devtmpfs 110568 0 110568 0% /dev tmpfs 23768 232 23536 1% /run tmpfs 5120 0 5120 0% /run/lock tmpfs 47520 0 47520 0% /run/shm /dev/mmcblk0p1 57288 18960 38328 34% /boot /dev/sda1 4006852 1591764 2415088 40% /media/usb </pre> Der letzte Eintrag ist der interessante: /dev/sda1 ist nach /media/usb gemountet. Wenn man sich nicht sicher ist, kann man vorher von einem anderen PC eine Datei auf dem USB-Stick ablegen und mit ls /media/usb prüfen, ob diese vorhanden ist. (Es kann sein, dass man die Berechtigung auf den Mouting-Point noch anpassen muss, da der Artikels etwas später als das damalige Einrichten entstand, bin ich mir nicht absolut sicher) = Das Zeitraffer-Script = Die Kamera funktioniert, der Zusatzspeicher ist da - nun fehlt nur noch die zeitgesteuerte Aufnahme. Am einfachsten geht das über ein kleines Script, das wahlweise direkt im Benutzerordner (home) angelegt werden kann. Der schnellste Weg nach Hause führt über den Befehl cd. Über den Befehl <pre> $ nano timeshot.sh </pre> wird Nano für die (noch nicht vorhandene) Datei timeshot.sh geöffnet. Dort kann nun folgender Code eingefügt werden: <geshi lang="bash"> #!/bin/sh dt=$(date +"%Y-%m-%d") time_now=$(date +%s) time_mid=$(date -d "00:00" +%s) mins=$((($time_now-$time_mid)/60)) timestamp=`printf "%04d" $mins` dstdir=/media/usb/timelapse/$dt/ mkdir -p $dstdir fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 $dstdir/img_$timestamp.jpg </geshi> Ganz oben kommt erst einmal der Shebang, anschließend werden ein paar Variablen definiert: In der Variable dt steht das aktuelle Datum im Format "Jahr-Monat-Datum", anschließend wird in die Variablen time_now und time_mid der Unix-Timestamp (also die Sekunden seit dem 01.01.1970) für die aktuelle Zeit und Mitternacht des aktuellen Tags geschrieben. Anschließend wird die Differenz der beiden Werte berechnet und durch 60 geteilt. Mit dem Befehl `printf "%04d" $mins` wird die Zahl auf alles "vor dem Komma" abgeschnitten und auf 4 Zeichen mit Nullen gefüllt und in die Variable timestamp geschrieben. In timestamp steht also nichts anderes als die aktuelle Minute des Tages. Warum? Später mehr dazu. dstdir gibt, wie sich erahnen lässt, das Zielverzeichnis des Bildes an, wobei der Ordner in der tiefsten Ebene dem aktuellen Datum entspricht. Existiert dieses Verzeichnis nicht, wird es über mkdir angelegt. Im letzten Befehl wird das bereits bekannte Programm fswebcam aufgerufen. Der endgültige Dateiname wird hier noch zusammengebaut. Vor die Minute des Tages wird noch ein "img_" vorangestellt und noch ein ".jpg" angehängt, damit die Dateien auch einen "Nachnamen" haben. Mit Strg+X, y, Enter ist die Datei im Dateisystem, kann aber noch nicht ausgeführt werden. Über den Befehl <pre> $ chmod 766 </pre> gibt man der Datei Ausführungsrechte für den eigenen Benutzer. Führt man sie nun aus, bringt sie zumindest bei mir eine Warnung (die man aber ignorieren kann): <pre> $ ./timeshot.sh Corrupt JPEG data: 1 extraneous bytes before marker 0xd0 </pre> Damit man nun nicht jede Minute vor dem Rechner verbringen muss, ist es zumindest empfehlenswert, die Aufnahme zeitgesteuert auszuführen. Dafür gibt es unter Linux crontab (Zeitplan). Mit dem Befehl crontab -e öffnet man diesen für den aktuellen Benutzer. Ganz am Ende der Datei kann man nun folgendes eintragen: <pre> * * * * * /home/pi/timeshot.sh </pre> Was da auf den ersten Blick etwas kryptisch aussieht ist es eigentlich nicht. /home/pi/timeshot.sh deutet zumindest einmal auf die Datei hin, die ausgeführt wird. Die Sterne vorne sind Wildcards, und bedeutet so viel wie "jede". In Cron gibt man vorne die Ausführung für die Minuten, Stunden, Tage im Monat, den Monaten und Wochentage an. Die 5 Sterne bedeuten also: "Führe die hintenstehende Datei jede Minute, jede Stunde, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Will man in der Nacht keine schwarzen Bilder sammeln, kann man auch folgende Zeile verwenden: <pre> * 6-21 * * * /home/pi/timeshot.sh </pre> Heißt dann so viel wie: "Führe die hintenstehende Datei jede Minute, in den Stunden von 6 bis 21, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Damit ist aber nicht "von 6 bis 21 Uhr!" gemeint - es werden Bilder von 6:00 Uhr bis 21:59 Uhr aufgenommen. = Videos basteln = (kommt die nächsten Tage) [[Kategorie:Software]] [[Kategorie:Linux]] [[Kategorie:Raspberry Pi]] efa982c0fd5e2dbd78ad14cc89ef2060770a1c99 859 858 2013-11-10T14:42:31Z Chris 2 wikitext text/x-wiki Was macht man mit einem stromsparenden Computer und einer Webcam? Die Frage habe ich mir genau zur letzten Lernphase meines Studiums gestellt und gleich mal auf die Probe gestellt, ob es möglich ist, innerhalb einer Mittagspause eine Zeitraffer-Kamera zu basteln (siehe auch [http://hobbyelektronik.org/b/2013/06/ein-tag/ hier]). Wenn man als Bash-Anfänger die die Dauer der Mittagspause an die südländische Siesta annähert kann ich schon vorweg sagen: Ja, es ist möglich! = Ausgangsmaterial = Als Computer kommt der Raspberry Pi zum Einsatz. Als Webcam dient eine Logitech C310. Um die SD-Karte etwas zu schonen darf ein billiger USB-Stick zum Einsatz, der nur als Aufnahmeziel dient. = Einrichten = == Kamera == Da es sich bei der Webcam um eine mit USB-Anschluss handelt, kann sie (meines Wissens) nicht ausschließlich mit dem verwendet werden, das Raspian hergibt. Mit dem Befehl lsusb kann man herausfinden, was am USB hängt: <pre> $ lsusb Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 058f:6387 Alcor Micro Corp. Flash Drive Bus 001 Device 005: ID 046d:081b Logitech, Inc. Webcam C310 </pre> Die Webcam ist also am Computer anhängig, genauso wie der USB-Stick. Über den Befehl ls /dev/video* werden alle Geräte angezeigt, die mit dem Namen video anfangen. Wurden also Treiber für die Kamera gefunden, erscheint sie in der Ausgabe: <pre> $ ls /dev/video* /dev/video0 </pre> Weil cat /dev/video0 > foo.jpg nicht so wirklich funktioniert, muss ein Vermittler her. Ich habe gute Erfahrungen mit fswebcam gemacht. Installation und Test sehen wie folgt aus: <pre> $ sudo apt-get install fswebcam [...] $ fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 testimg.jpg </pre> Der letztere Befehl nimmt ein Bild mit der Auflösung (Parameter -r) 1280x960 auf. Das -q nach der Qualitätsstufe (hier: 85) ist Absicht - bei dem Parameter handelt es sich nicht um -q wie quality, sondern um quiet. Mit -d wird das Device gewählt und anschließend folgt die Ausgabedatei. Diese kann, sofern ein Webserver installiert ist, nach /var/www verschieben oder natürlich direkt auf dem Computer ansehen. In meinem Fall wird der Raspberry "headless" betrieben und die Datei über SSH-Filetransfer auf den Haupt-PC befördert. Funktioniert die Kamera, kann der USB-Speicher angedockt werden: == USB-Stick einbinden == Viele Wege führen bekanntlich nach Rom, genauso kann man Speicher auf verschiedene Weisen einbinden. Das hier ist eine. Zunächst muss ein Verzeichnis angelegt werden, in das der USB-Stick später eingebunden (gemountet) wird. In meinem Fall ist dies /media/usb: <pre> mkdir /media/usb </pre> Nun muss herausgefunden werden, wie man den Speicher anspricht. Am besten verwendet man dessen [[wpde:Universally Unique Identifier|Universally Unique Identifier]] (kurz UUID). Der Vorteil an diesem ist, wie der Name schon sagt, dass er Eindeutig ist. Mit dem Befehl blkid können die UUIDs aller verfügbaren Speicher angezeigt werden: <pre> $ blkid /dev/sda1: UUID="0CA5-719C" TYPE="vfat" LABEL="KINGSTON" /dev/mmcblk0p1: SEC_TYPE="msdos" UUID="C522-EA52" TYPE="vfat" /dev/mmcblk0p2: UUID="62ba9ec9-47d9-4421-aaee-71dd6c0f3707" TYPE="ext4" </pre> In geistiger Umnachtung habe ich den USB-Stick "KINGSTON" genannt, das hat allerdings keine Bedeutung. Wichtig ist das, was hinter "UUID=" steht. Man kann den Stick zwar schnell mit mount einbinden, nach dem nächsten Neustart hat man ihn aber verloren und das passiert - auch wenn das System stabil läuft - mit Sicherheit. Also muss er in die fstab (file system table) eingetragen werden. Da man mit ihr nicht spielt, muss sie mit Superuser-Rechten bearbeitet werden: <pre> $ sudo nano /etc/fstab </pre> Die bereits vorhandenen Einträge kann man ignorieren, hier muss der zu verwendende USB-Stick hinzugefügt werden. Ist dieser mit FAT formatiert und hat die UUID 0CA5-719C, kann folgende Zeile an das Ende der Datei geschrieben werden: <pre> UUID=0CA5-719C /media/usb/ vfat defaults,auto,users,noatime,umask=000,rw 0 0 </pre> Mit Strg+X Schließen und das Speichern mit Y und Druck auf die Enter-Taste bestätigen. Navigiert man unter /media/usb kann man nun wunderbar Dateien anlegen, ABER: Diese befinden sich NICHT auf dem USB-Stick! fstab wird nur beim Neustart gelesen. Also heißt es <pre> $ sudo reboot </pre> eingeben und somit die Uptime auf 0 zurücksetzen. Mit dem Befehl df kann jetzt überprüft werden, ob der Speicher richtig eingebunden wurde. Gleichzeitig sieht man auch, wie viel Speicher bereits genutzt wird: <pre> $ df Filesystem 1K-blocks Used Available Use% Mounted on rootfs 1838936 1775400 0 100% / /dev/root 1838936 1775400 0 100% / devtmpfs 110568 0 110568 0% /dev tmpfs 23768 232 23536 1% /run tmpfs 5120 0 5120 0% /run/lock tmpfs 47520 0 47520 0% /run/shm /dev/mmcblk0p1 57288 18960 38328 34% /boot /dev/sda1 4006852 1591764 2415088 40% /media/usb </pre> Der letzte Eintrag ist der interessante: /dev/sda1 ist nach /media/usb gemountet. Wenn man sich nicht sicher ist, kann man vorher von einem anderen PC eine Datei auf dem USB-Stick ablegen und mit ls /media/usb prüfen, ob diese vorhanden ist. (Es kann sein, dass man die Berechtigung auf den Mouting-Point noch anpassen muss, da der Artikels etwas später als das damalige Einrichten entstand, bin ich mir nicht absolut sicher) = Das Zeitraffer-Script = Die Kamera funktioniert, der Zusatzspeicher ist da - nun fehlt nur noch die zeitgesteuerte Aufnahme. Am einfachsten geht das über ein kleines Script, das wahlweise direkt im Benutzerordner (home) angelegt werden kann. Der schnellste Weg nach Hause führt über den Befehl cd. Über den Befehl <pre> $ nano timeshot.sh </pre> wird Nano für die (noch nicht vorhandene) Datei timeshot.sh geöffnet. Dort kann nun folgender Code eingefügt werden: <geshi lang="bash"> #!/bin/sh dt=$(date +"%Y-%m-%d") time_now=$(date +%s) time_mid=$(date -d "00:00" +%s) mins=$((($time_now-$time_mid)/60)) timestamp=`printf "%04d" $mins` dstdir=/media/usb/timelapse/$dt/ mkdir -p $dstdir fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 $dstdir/img_$timestamp.jpg </geshi> Ganz oben kommt erst einmal der Shebang, anschließend werden ein paar Variablen definiert: In der Variable dt steht das aktuelle Datum im Format "Jahr-Monat-Datum", anschließend wird in die Variablen time_now und time_mid der Unix-Timestamp (also die Sekunden seit dem 01.01.1970) für die aktuelle Zeit und Mitternacht des aktuellen Tags geschrieben. Anschließend wird die Differenz der beiden Werte berechnet und durch 60 geteilt. Mit dem Befehl `printf "%04d" $mins` wird die Zahl auf alles "vor dem Komma" abgeschnitten und auf 4 Zeichen mit Nullen gefüllt und in die Variable timestamp geschrieben. In timestamp steht also nichts anderes als die aktuelle Minute des Tages. Warum? Später mehr dazu. dstdir gibt, wie sich erahnen lässt, das Zielverzeichnis des Bildes an, wobei der Ordner in der tiefsten Ebene dem aktuellen Datum entspricht. Existiert dieses Verzeichnis nicht, wird es über mkdir angelegt. Im letzten Befehl wird das bereits bekannte Programm fswebcam aufgerufen. Der endgültige Dateiname wird hier noch zusammengebaut. Vor die Minute des Tages wird noch ein "img_" vorangestellt und noch ein ".jpg" angehängt, damit die Dateien auch einen "Nachnamen" haben. Mit Strg+X, y, Enter ist die Datei im Dateisystem, kann aber noch nicht ausgeführt werden. Über den Befehl <pre> $ chmod 766 </pre> gibt man der Datei Ausführungsrechte für den eigenen Benutzer. Führt man sie nun aus, bringt sie zumindest bei mir eine Warnung (die man aber ignorieren kann): <pre> $ ./timeshot.sh Corrupt JPEG data: 1 extraneous bytes before marker 0xd0 </pre> Damit man nun nicht jede Minute vor dem Rechner verbringen muss, ist es zumindest empfehlenswert, die Aufnahme zeitgesteuert auszuführen. Dafür gibt es unter Linux crontab (Zeitplan). Mit dem Befehl crontab -e öffnet man diesen für den aktuellen Benutzer. Ganz am Ende der Datei kann man nun folgendes eintragen: <pre> * * * * * /home/pi/timeshot.sh </pre> Was da auf den ersten Blick etwas kryptisch aussieht ist es eigentlich nicht. /home/pi/timeshot.sh deutet zumindest einmal auf die Datei hin, die ausgeführt wird. Die Sterne vorne sind Wildcards, und bedeutet so viel wie "jede". In Cron gibt man vorne die Ausführung für die Minuten, Stunden, Tage im Monat, den Monaten und Wochentage an. Die 5 Sterne bedeuten also: "Führe die hintenstehende Datei jede Minute, jede Stunde, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Will man in der Nacht keine schwarzen Bilder sammeln, kann man auch folgende Zeile verwenden: <pre> * 6-21 * * * /home/pi/timeshot.sh </pre> Heißt dann so viel wie: "Führe die hintenstehende Datei jede Minute, in den Stunden von 6 bis 21, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Damit ist aber nicht "von 6 bis 21 Uhr!" gemeint - es werden Bilder von 6:00 Uhr bis 21:59 Uhr aufgenommen. = Bilder verarbeiten = Fotos einfach der der Bilder aufnehmen macht natürlich wenig Sinn. Zunächst ist aber erst einmal die Frage: Wie viel Daten kommen überhaupt zusammen? In meinem Fall - jede Minute (also 1440 am Tag) ein Bild 1280x960 bei 85 % Qualität sammeln sich am Tag etwa 85 MiB an. Was macht man damit? Hier ein paar Vorschläge: = Video = Naheliegend ist natürlich, ein Video der Fotos zu erstellen. Nichts leichter als das! Das ist auch der Grund, warum sie nach dem oben angegebenen Schema durchnummeriert sind. Dateien mit diesem Schema lassen sich direkt mit [http://www.ffmpeg.org FFmpeg] verarbeiten. Ich wollte es auf dem Raspberry Pi machen, musste aber sehr schnell einsehen, dass man es schlichtweg vergessen kann, zumindest bei meinen Parametern - h.264 bei 2,5 Mbit/s Bitrate. Die ersten Bilder werden noch relativ schnell zusammengefügt, irgendwann kommt man aber deutlich unter 1 fps beim Codieren. Vermutlich scheitert es hier beim RAM und vermutlich verwendet FFmpeg den in Hardware vorhandenen h.264-Codec nicht. Der Desktop-PC hat da deutlich mehr Power. Also Bilder übertragen, in dem Ordner eine Kommandozeile öffnen und folgenden Befehl reinklöppeln: <pre> ffmpeg.exe -f image2 -i img_%04d.jpg -vcodec libx264 -vb 2500k -acodec null -r 25 day.mp4 </pre> Die Magie kommt vom Parameter -i, in dem alle Bilder mit dem Format img_%04d.jpg zusammengestückelt werden. Wer den Befehl in eine Batch-Datei stecken möchte, muss das % durch %% ersetzen, damit das "%0" nicht interpretiert wird. Allerdings gibt es ein kleines Problem: Fehlt ein Bild, wird die Erstellung dort beendet. [[Kategorie:Software]] [[Kategorie:Linux]] [[Kategorie:Raspberry Pi]] 450800d288da61d10f610f314c201d3f053086f7 868 859 2013-11-10T16:12:52Z Chris 2 fertsch. wikitext text/x-wiki Was macht man mit einem stromsparenden Computer und einer Webcam? Die Frage habe ich mir genau zur letzten Lernphase meines Studiums gestellt und gleich mal auf die Probe gestellt, ob es möglich ist, innerhalb einer Mittagspause eine Zeitraffer-Kamera zu basteln (siehe auch [http://hobbyelektronik.org/b/2013/06/ein-tag/ hier]). Wenn man als Bash-Anfänger die die Dauer der Mittagspause an die südländische Siesta annähert kann ich schon vorweg sagen: Ja, es ist möglich! = Ausgangsmaterial = Als Computer kommt der Raspberry Pi zum Einsatz. Als Webcam dient eine Logitech C310. Um die SD-Karte etwas zu schonen kommt ein billiger USB-Stick zum Einsatz, der nur als Aufnahmeziel dient. = Einrichten = == Kamera == Da es sich bei der Webcam um eine mit USB-Anschluss handelt, kann sie (meines Wissens) nicht ausschließlich mit dem verwendet werden, das Raspian hergibt. Mit dem Befehl lsusb kann man herausfinden, was am USB hängt: <pre> $ lsusb Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 058f:6387 Alcor Micro Corp. Flash Drive Bus 001 Device 005: ID 046d:081b Logitech, Inc. Webcam C310 </pre> Die Webcam ist also am Computer anhängig, genauso wie der USB-Stick. Über den Befehl ls /dev/video* werden alle Geräte angezeigt, die mit dem Namen video anfangen. Wurden also Treiber für die Kamera gefunden, erscheint sie in der Ausgabe: <pre> $ ls /dev/video* /dev/video0 </pre> Weil cat /dev/video0 > foo.jpg nicht so wirklich funktioniert, muss ein Vermittler her. Ich habe gute Erfahrungen mit fswebcam gemacht. Installation und Test sehen wie folgt aus: <pre> $ sudo apt-get install fswebcam [...] $ fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 testimg.jpg </pre> Der letztere Befehl nimmt ein Bild mit der Auflösung (Parameter -r) 1280x960 auf. Das -q nach der Qualitätsstufe (hier: 85) ist Absicht - bei dem Parameter handelt es sich nicht um -q wie quality, sondern um quiet. Mit -d wird das Device gewählt und anschließend folgt die Ausgabedatei. Diese kann, sofern ein Webserver installiert ist, nach /var/www verschieben oder natürlich direkt auf dem Computer ansehen. In meinem Fall wird der Raspberry "headless" betrieben und die Datei über SSH-Filetransfer auf den Haupt-PC befördert. Funktioniert die Kamera, kann der USB-Speicher angedockt werden: == USB-Stick einbinden == Viele Wege führen bekanntlich nach Rom, genauso kann man Speicher auf verschiedene Weisen einbinden. Das hier ist eine. Zunächst muss ein Verzeichnis angelegt werden, in das der USB-Stick später eingebunden (gemountet) wird. In meinem Fall ist dies /media/usb: <pre> mkdir /media/usb </pre> Nun muss herausgefunden werden, wie man den Speicher anspricht. Am besten verwendet man dessen [[wpde:Universally Unique Identifier|Universally Unique Identifier]] (kurz UUID). Der Vorteil an diesem ist, wie der Name schon sagt, dass er Eindeutig ist. Mit dem Befehl blkid können die UUIDs aller verfügbaren Speicher angezeigt werden: <pre> $ blkid /dev/sda1: UUID="0CA5-719C" TYPE="vfat" LABEL="KINGSTON" /dev/mmcblk0p1: SEC_TYPE="msdos" UUID="C522-EA52" TYPE="vfat" /dev/mmcblk0p2: UUID="62ba9ec9-47d9-4421-aaee-71dd6c0f3707" TYPE="ext4" </pre> In geistiger Umnachtung habe ich den USB-Stick "KINGSTON" genannt, das hat allerdings keine Bedeutung. Wichtig ist das, was hinter "UUID=" steht. Man kann den Stick zwar schnell mit mount einbinden, nach dem nächsten Neustart hat man ihn aber verloren und das passiert - auch wenn das System stabil läuft - mit Sicherheit. Also muss er in die fstab (file system table) eingetragen werden. Da man mit ihr nicht spielt, muss sie mit Superuser-Rechten bearbeitet werden: <pre> $ sudo nano /etc/fstab </pre> Die bereits vorhandenen Einträge kann man ignorieren, hier muss der zu verwendende USB-Stick hinzugefügt werden. Ist dieser mit FAT formatiert und hat die UUID 0CA5-719C, kann folgende Zeile an das Ende der Datei geschrieben werden: <pre> UUID=0CA5-719C /media/usb/ vfat defaults,auto,users,noatime,umask=000,rw 0 0 </pre> Mit Strg+X Schließen und das Speichern mit Y und Druck auf die Enter-Taste bestätigen. Navigiert man unter /media/usb kann man nun wunderbar Dateien anlegen, ABER: Diese befinden sich NICHT auf dem USB-Stick! fstab wird nur beim Neustart gelesen. Also heißt es <pre> $ sudo reboot </pre> eingeben und somit die Uptime auf 0 zurücksetzen. Mit dem Befehl df kann jetzt überprüft werden, ob der Speicher richtig eingebunden wurde. Gleichzeitig sieht man auch, wie viel Speicher bereits genutzt wird: <pre> $ df Filesystem 1K-blocks Used Available Use% Mounted on rootfs 1838936 1775400 0 100% / /dev/root 1838936 1775400 0 100% / devtmpfs 110568 0 110568 0% /dev tmpfs 23768 232 23536 1% /run tmpfs 5120 0 5120 0% /run/lock tmpfs 47520 0 47520 0% /run/shm /dev/mmcblk0p1 57288 18960 38328 34% /boot /dev/sda1 4006852 1591764 2415088 40% /media/usb </pre> Der letzte Eintrag ist der interessante: /dev/sda1 ist nach /media/usb gemountet. Wenn man sich nicht sicher ist, kann man vorher von einem anderen PC eine Datei auf dem USB-Stick ablegen und mit ls /media/usb prüfen, ob diese vorhanden ist. (Es kann sein, dass man die Berechtigung auf den Mouting-Point noch anpassen muss, da der Artikels etwas später als das damalige Einrichten entstand, bin ich mir nicht absolut sicher) = Das Zeitraffer-Script = Die Kamera funktioniert, der Zusatzspeicher ist da - nun fehlt nur noch die zeitgesteuerte Aufnahme. Am einfachsten geht das über ein kleines Script, das wahlweise direkt im Benutzerordner (home) angelegt werden kann. Der schnellste Weg nach Hause führt über den Befehl cd. Über den Befehl <pre> $ nano timeshot.sh </pre> wird Nano für die (noch nicht vorhandene) Datei timeshot.sh geöffnet. Dort kann nun folgender Code eingefügt werden: <geshi lang="bash"> #!/bin/sh dt=$(date +"%Y-%m-%d") time_now=$(date +%s) time_mid=$(date -d "00:00" +%s) mins=$((($time_now-$time_mid)/60)) timestamp=`printf "%04d" $mins` dstdir=/media/usb/timelapse/$dt/ mkdir -p $dstdir fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 $dstdir/img_$timestamp.jpg </geshi> Ganz oben kommt erst einmal der Shebang, anschließend werden ein paar Variablen definiert: In der Variable dt steht das aktuelle Datum im Format "Jahr-Monat-Datum", anschließend wird in die Variablen time_now und time_mid der Unix-Timestamp (also die Sekunden seit dem 01.01.1970) für die aktuelle Zeit und Mitternacht des aktuellen Tags geschrieben. Anschließend wird die Differenz der beiden Werte berechnet und durch 60 geteilt. Mit dem Befehl `printf "%04d" $mins` wird die Zahl auf alles "vor dem Komma" abgeschnitten und auf 4 Zeichen mit Nullen gefüllt und in die Variable timestamp geschrieben. In timestamp steht also nichts anderes als die aktuelle Minute des Tages. Warum? Später mehr dazu. dstdir gibt, wie sich erahnen lässt, das Zielverzeichnis des Bildes an, wobei der Ordner in der tiefsten Ebene dem aktuellen Datum entspricht. Existiert dieses Verzeichnis nicht, wird es über mkdir angelegt. Im letzten Befehl wird das bereits bekannte Programm fswebcam aufgerufen. Der endgültige Dateiname wird hier noch zusammengebaut. Vor die Minute des Tages wird noch ein "img_" vorangestellt und noch ein ".jpg" angehängt, damit die Dateien auch einen "Nachnamen" haben. Mit Strg+X, y, Enter ist die Datei im Dateisystem, kann aber noch nicht ausgeführt werden. Über den Befehl <pre> $ chmod 766 </pre> gibt man der Datei Ausführungsrechte für den eigenen Benutzer. Führt man sie nun aus, bringt sie zumindest bei mir eine Warnung (die man aber ignorieren kann): <pre> $ ./timeshot.sh Corrupt JPEG data: 1 extraneous bytes before marker 0xd0 </pre> Damit man nun nicht jede Minute vor dem Rechner verbringen muss, ist es zumindest empfehlenswert, die Aufnahme zeitgesteuert auszuführen. Dafür gibt es unter Linux crontab (Zeitplan). Mit dem Befehl crontab -e öffnet man diesen für den aktuellen Benutzer. Ganz am Ende der Datei kann man nun folgendes eintragen: <pre> * * * * * /home/pi/timeshot.sh </pre> Was da auf den ersten Blick etwas kryptisch aussieht ist es eigentlich nicht. /home/pi/timeshot.sh deutet zumindest einmal auf die Datei hin, die ausgeführt wird. Die Sterne vorne sind Wildcards, und bedeutet so viel wie "jede". In Cron gibt man vorne die Ausführung für die Minuten, Stunden, Tage im Monat, den Monaten und Wochentage an. Die 5 Sterne bedeuten also: "Führe die hintenstehende Datei jede Minute, jede Stunde, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Will man in der Nacht keine schwarzen Bilder sammeln, kann man auch folgende Zeile verwenden: <pre> * 6-21 * * * /home/pi/timeshot.sh </pre> Heißt dann so viel wie: "Führe die hintenstehende Datei jede Minute, in den Stunden von 6 bis 21, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Damit ist aber nicht "von 6 bis 21 Uhr!" gemeint - es werden Bilder von 6:00 Uhr bis 21:59 Uhr aufgenommen. = Bilder verarbeiten = Fotos einfach der der Bilder aufnehmen macht natürlich wenig Sinn. Zunächst ist aber erst einmal die Frage: Wie viel Daten kommen überhaupt zusammen? In meinem Fall - jede Minute (also 1440 am Tag) ein Bild 1280x960 bei 85 % Qualität sammeln sich am Tag etwa 85 MiB an. Was macht man damit? Hier ein paar Vorschläge: == Video == Naheliegend ist natürlich, ein Video der Fotos zu erstellen. Nichts leichter als das! Das ist auch der Grund, warum sie nach dem oben angegebenen Schema durchnummeriert sind. Dateien mit diesem Schema lassen sich direkt mit [http://www.ffmpeg.org FFmpeg] verarbeiten. Ich wollte es auf dem Raspberry Pi machen, musste aber sehr schnell einsehen, dass man es schlichtweg vergessen kann, zumindest bei meinen Parametern - h.264 bei 2,5 Mbit/s Bitrate. Die ersten Bilder werden noch relativ schnell zusammengefügt, irgendwann kommt man aber deutlich unter 1 fps beim Codieren. Vermutlich scheitert es hier beim RAM und vermutlich verwendet FFmpeg den in Hardware vorhandenen h.264-Codec nicht. Der Desktop-PC hat da deutlich mehr Power. Also Bilder übertragen, in dem Ordner eine Kommandozeile öffnen und folgenden Befehl reinklöppeln: <pre> ffmpeg.exe -f image2 -i img_%04d.jpg -vcodec libx264 -vb 2500k -acodec null -r 25 day.mp4 </pre> Die Magie kommt vom Parameter -i, in dem alle Bilder mit dem Format img_%04d.jpg zusammengestückelt werden. Wer den Befehl in eine Batch-Datei stecken möchte, muss das % durch %% ersetzen, damit das "%0" nicht interpretiert wird. Allerdings gibt es ein kleines Problem: Fehlt ein Bild, wird die Erstellung dort beendet. Um diesem Problem zu gehen, habe ich ein kleines PHP-Script geschrieben, das hierfür Platzhalter einfügt: <geshi lang="php"> <?php $w = 1280; $h = 960; $name_min = 0; $name_max = 1439; $name_digits = 4; $name_format = "img_#.jpg"; $im = imagecreatetruecolor($w, $h); $col = imagecolorallocate($im, 0, 0, 255); imagefilledrectangle($im, 0, 0, $w, $h, $col); for($i = $name_min; $i <= $name_max; $i++) { $digits = str_pad($i, $name_digits, "0", STR_PAD_LEFT); $fname = str_replace("#", $digits, $name_format); if(!is_file($fname)) { echo "file " . $fname . " not found - create.\n"; imagejpeg($im, $fname, 85); } } </geshi> Das Script macht nichts anderes als Dateien mit dem Format "img_#.jpg" zu suchen, wobei # durch eine mit Nullen auf vier aufgefüllten Zahl von 0 bis 1439 ersetzt wird. Ist eine Datei nicht vorhanden, wird für diese das vorbereite Bild als JPEG geschrieben. Wer will, kann anstelle des imagefilledrectangle natürlich jeden anderen Befehl zur Bildmanipulation einsetzen. == Tagesbild == Nicht wirklich aussagekräftig, aber eine nette Spielerei, die im Prinzip ganz einfach ist: Man nimmt von jedem Einzelbild einen von der Uhrzeit abhängigen Streifen heraus und baut damit ein neues Bild, das aus (fast) allen Bildern des Tages zusammengebaut wurde. Da die 1280 Pixel Bildbreite schon relativ nah an den 1400 Bildern pro Tag sind, habe ich vertikale Streifen verwendet. Der Einfachheit halber ist das Script ebenfalls in PHP zusammengeschustert: <geshi lang="php"> $folder = "/bilder/"; $dst = imagecreatetruecolor(1280, 960); $red = imagecolorallocate($dst, 255, 0, 0); imagefilledrectangle($dst, 0,0,1280,960, $red); for($i = 0; $i < 1280; $i++) { $file = $folder."/img_".str_pad($i+160, 4, "0", STR_PAD_LEFT).".jpg"; if(is_file($file)) { echo "."; $src = imagecreatefromjpeg($file); imagecopyresampled($dst, $src, $i, 0, $i, 0, 1, 1280, 1, 1280); imagedestroy($src); } else { echo "#"; } } echo "\n"; imagejpeg($dst, $folder.".jpg", 90); imagedestroy($dst); </geshi> Nicht ganz so übersichtlich wie das vorherige Script. Im Prinzip wird für jedes Bild (es wird erst ab Bild 160 eingelesen, damit es 1280 Streifen werden) ein imagecopyresampled in das Zielbild durchgeführt, wobei jeder Streifen 1 Pixel breit ist. Ursprünglich wollte ich jede Streifen 2 bzw. 3 Pixel breit machen und die die "linken" mit leicht überblenden, damit es keine harten Kanten gibt. Nur scheint das in PHP nicht so ganz trivial zu sein. Hier aber ein paar Ergebnisse der Tagesbilder: <gallery> Datei:timelapse_2013-06-14.jpg|14.06.2013 Datei:timelapse_2013-06-17.jpg|17.06.2013 Datei:timelapse_2013-06-21.jpg|21.06.2013 Datei:timelapse_2013-07-01.jpg|01.07.2013 Datei:timelapse_2013-07-09.jpg|09.07.2013 Datei:timelapse_2013-07-19.jpg|19.07.2013 Datei:timelapse_2013-07-23.jpg|23.07.2013 Datei:timelapse_2013-07-31.jpg|31.07.2013 </gallery> == Webserver == Natürlich kann man, wenn man das aktuelle Webcam-Bild auf einer Internetseite einbinden will, jede Minute mit immer gleichem Namen in den /var/www-Ordner kopieren lassen. Normalerweise sollte das Betriebssystem die Datei auch im RAM cachen. Trotzdem kann es sein, dass das Ganze unnütze Schreibzyklen auf dem Flash-Speicher erzeugt und somit für eine schnellere Alterung sorgt. Mit folgendem PHP-Script lässt sich das aktuelle Bild von einem anderen Ort im Dateisystem lesen und in den Webspace holen: <geshi lang="PHP"> <?php $img_path = "/media/usb/timelapse/#d/img_#m.jpg"; $date = date("Y-m-d"); $minute = date("H") * 60 + date("i"); $search = array("#d", "#m"); $replace = array($date, $minute); $file = str_replace($search, $replace, $img_path); header("Content-Type: Content-Type: image/jpeg"); header("Cache-Control: no-cache, must-revalidate"); if(is_file($file)) { readfile($file); } else { $w = 1280; $h = 960; $im = imagecreatetruecolor($w, $h); $col = imagecolorallocate($im, 0, 0, 255); imagefilledrectangle($im, 0, 0, $w, $h, $col); imagejpeg($im); } </geshi> Dafür muss man aber dem Benutzer des Webservers mindestens Leserechte in den entsprechenden Ordnern geben! = Anmerkungen = Hier noch ein paar Dinge, die mir beim Betreiben der Kamera aufgefallen sind: * Auch halbwegs moderne Bildsensoren [http://hobbyelektronik.org/b/2013/06/ein-tag/ mögen keine dauerhafte Sonneneinstrahlung] * Die Logitech-Kamera oder deren Treiber stürzen ab und zu ab und reißen den kompletten Raspberry Pi herunter [[Kategorie:Software]] [[Kategorie:Linux]] [[Kategorie:Raspberry Pi]] d33d2c73512b6e03ea7305fead223595b6c63c4d 869 868 2013-11-10T16:15:27Z Chris 2 kleine Änderungen wikitext text/x-wiki Was macht man mit einem stromsparenden Computer und einer Webcam? Die Frage habe ich mir genau zur letzten Lernphase meines Studiums gestellt und gleich mal auf die Probe gestellt, ob es möglich ist, innerhalb einer Mittagspause eine Zeitraffer-Kamera zu basteln (siehe auch [http://hobbyelektronik.org/b/2013/06/ein-tag/ hier]). Wenn man als Bash-Anfänger die die Dauer der Mittagspause an die südländische Siesta annähert kann ich schon vorweg sagen: Ja, es ist möglich! = Ausgangsmaterial = Als Computer kommt der Raspberry Pi zum Einsatz. Als Webcam dient eine Logitech C310. Um die SD-Karte etwas zu schonen kommt ein billiger USB-Stick zum Einsatz, der nur als Aufnahmeziel dient. = Einrichten = == Kamera == Da es sich bei der Webcam um eine mit USB-Anschluss handelt, kann sie (meines Wissens) nicht ausschließlich mit dem verwendet werden, das Raspian hergibt. Mit dem Befehl lsusb kann man herausfinden, was am USB hängt: <pre> $ lsusb Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 058f:6387 Alcor Micro Corp. Flash Drive Bus 001 Device 005: ID 046d:081b Logitech, Inc. Webcam C310 </pre> Die Webcam ist also am Computer anhängig, genauso wie der USB-Stick. Über den Befehl ls /dev/video* werden alle Geräte angezeigt, die mit dem Namen video anfangen. Wurden also Treiber für die Kamera gefunden, erscheint sie in der Ausgabe: <pre> $ ls /dev/video* /dev/video0 </pre> Weil cat /dev/video0 > foo.jpg nicht so wirklich funktioniert, muss ein Vermittler her. Ich habe gute Erfahrungen mit fswebcam gemacht. Installation und Test sehen wie folgt aus: <pre> $ sudo apt-get install fswebcam [...] $ fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 testimg.jpg </pre> Der letztere Befehl nimmt ein Bild mit der Auflösung (Parameter -r) 1280x960 auf. Das -q nach der Qualitätsstufe (hier: 85) ist Absicht - bei dem Parameter handelt es sich nicht um -q wie quality, sondern um quiet. Mit -d wird das Device gewählt und anschließend folgt die Ausgabedatei. Diese kann, sofern ein Webserver installiert ist, nach /var/www verschieben oder natürlich direkt auf dem Computer ansehen. In meinem Fall wird der Raspberry "headless" betrieben und die Datei über SSH-Filetransfer auf den Haupt-PC befördert. Funktioniert die Kamera, kann der USB-Speicher angedockt werden: == USB-Stick einbinden == Viele Wege führen bekanntlich nach Rom, genauso kann man Speicher auf verschiedene Weisen einbinden. Das hier ist eine. Zunächst muss ein Verzeichnis angelegt werden, in das der USB-Stick später eingebunden (gemountet) wird. In meinem Fall ist dies /media/usb: <pre> mkdir /media/usb </pre> Nun muss herausgefunden werden, wie man den Speicher anspricht. Am besten verwendet man dessen [[wpde:Universally Unique Identifier|Universally Unique Identifier]] (kurz UUID). Der Vorteil an diesem ist, wie der Name schon sagt, dass er Eindeutig ist. Mit dem Befehl blkid können die UUIDs aller verfügbaren Speicher angezeigt werden: <pre> $ blkid /dev/sda1: UUID="0CA5-719C" TYPE="vfat" LABEL="KINGSTON" /dev/mmcblk0p1: SEC_TYPE="msdos" UUID="C522-EA52" TYPE="vfat" /dev/mmcblk0p2: UUID="62ba9ec9-47d9-4421-aaee-71dd6c0f3707" TYPE="ext4" </pre> In geistiger Umnachtung habe ich den USB-Stick "KINGSTON" genannt, das hat allerdings keine Bedeutung. Wichtig ist das, was hinter "UUID=" steht. Man kann den Stick zwar schnell mit mount einbinden, nach dem nächsten Neustart hat man ihn aber verloren und das passiert - auch wenn das System stabil läuft - mit Sicherheit. Also muss er in die fstab (file system table) eingetragen werden. Da man mit ihr nicht spielt, muss sie mit Superuser-Rechten bearbeitet werden: <pre> $ sudo nano /etc/fstab </pre> Die bereits vorhandenen Einträge kann man ignorieren, hier muss der zu verwendende USB-Stick hinzugefügt werden. Ist dieser mit FAT formatiert und hat die UUID 0CA5-719C, kann folgende Zeile an das Ende der Datei geschrieben werden: <pre> UUID=0CA5-719C /media/usb/ vfat defaults,auto,users,noatime,umask=000,rw 0 0 </pre> Mit Strg+X Schließen und das Speichern mit Y und Druck auf die Enter-Taste bestätigen. Navigiert man unter /media/usb kann man nun wunderbar Dateien anlegen, ABER: Diese befinden sich NICHT auf dem USB-Stick! fstab wird nur beim Neustart gelesen. Also heißt es <pre> $ sudo reboot </pre> eingeben und somit die Uptime auf 0 zurücksetzen. Mit dem Befehl df kann jetzt überprüft werden, ob der Speicher richtig eingebunden wurde. Gleichzeitig sieht man auch, wie viel Speicher bereits genutzt wird: <pre> $ df Filesystem 1K-blocks Used Available Use% Mounted on rootfs 1838936 1775400 0 100% / /dev/root 1838936 1775400 0 100% / devtmpfs 110568 0 110568 0% /dev tmpfs 23768 232 23536 1% /run tmpfs 5120 0 5120 0% /run/lock tmpfs 47520 0 47520 0% /run/shm /dev/mmcblk0p1 57288 18960 38328 34% /boot /dev/sda1 4006852 1591764 2415088 40% /media/usb </pre> Der letzte Eintrag ist der interessante: /dev/sda1 ist nach /media/usb gemountet. Wenn man sich nicht sicher ist, kann man vorher von einem anderen PC eine Datei auf dem USB-Stick ablegen und mit ls /media/usb prüfen, ob diese vorhanden ist. (Es kann sein, dass man die Berechtigung auf den Mouting-Point noch anpassen muss, da der Artikels etwas später als das damalige Einrichten entstand, bin ich mir nicht absolut sicher) = Das Zeitraffer-Script = Die Kamera funktioniert, der Zusatzspeicher ist da - nun fehlt nur noch die zeitgesteuerte Aufnahme. Am einfachsten geht das über ein kleines Script, das wahlweise direkt im Benutzerordner (home) angelegt werden kann. Der schnellste Weg nach Hause führt über den Befehl cd. Über den Befehl <pre> $ nano timeshot.sh </pre> wird Nano für die (noch nicht vorhandene) Datei timeshot.sh geöffnet. Dort kann nun folgender Code eingefügt werden: <geshi lang="bash"> #!/bin/sh dt=$(date +"%Y-%m-%d") time_now=$(date +%s) time_mid=$(date -d "00:00" +%s) mins=$((($time_now-$time_mid)/60)) timestamp=`printf "%04d" $mins` dstdir=/media/usb/timelapse/$dt/ mkdir -p $dstdir fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 $dstdir/img_$timestamp.jpg </geshi> Ganz oben kommt erst einmal der Shebang, anschließend werden ein paar Variablen definiert: In der Variable dt steht das aktuelle Datum im Format "Jahr-Monat-Datum", anschließend wird in die Variablen time_now und time_mid der Unix-Timestamp (also die Sekunden seit dem 01.01.1970) für die aktuelle Zeit und Mitternacht des aktuellen Tags geschrieben. Anschließend wird die Differenz der beiden Werte berechnet und durch 60 geteilt. Mit dem Befehl `printf "%04d" $mins` wird die Zahl auf alles "vor dem Komma" abgeschnitten und auf 4 Zeichen mit Nullen gefüllt und in die Variable timestamp geschrieben. In timestamp steht also nichts anderes als die aktuelle Minute des Tages. Warum? Später mehr dazu. dstdir gibt, wie sich erahnen lässt, das Zielverzeichnis des Bildes an, wobei der Ordner in der tiefsten Ebene dem aktuellen Datum entspricht. Existiert dieses Verzeichnis nicht, wird es über mkdir angelegt. Im letzten Befehl wird das bereits bekannte Programm fswebcam aufgerufen. Der endgültige Dateiname wird hier noch zusammengebaut. Vor die Minute des Tages wird noch ein "img_" vorangestellt und noch ein ".jpg" angehängt, damit die Dateien auch einen "Nachnamen" haben. Mit Strg+X, y, Enter ist die Datei im Dateisystem, kann aber noch nicht ausgeführt werden. Über den Befehl <pre> $ chmod 766 </pre> gibt man der Datei Ausführungsrechte für den eigenen Benutzer. Führt man sie nun aus, bringt sie zumindest bei mir eine Warnung (die man aber ignorieren kann): <pre> $ ./timeshot.sh Corrupt JPEG data: 1 extraneous bytes before marker 0xd0 </pre> Damit man nun nicht jede Minute vor dem Rechner verbringen muss, ist es zumindest empfehlenswert, die Aufnahme zeitgesteuert auszuführen. Dafür gibt es unter Linux crontab (Zeitplan). Mit dem Befehl crontab -e öffnet man diesen für den aktuellen Benutzer. Ganz am Ende der Datei kann man nun folgendes eintragen: <pre> * * * * * /home/pi/timeshot.sh </pre> Was da auf den ersten Blick etwas kryptisch aussieht ist es eigentlich nicht. /home/pi/timeshot.sh deutet zumindest einmal auf die Datei hin, die ausgeführt wird. Die Sterne vorne sind Wildcards, und bedeutet so viel wie "jede". In Cron gibt man vorne die Ausführung für die Minuten, Stunden, Tage im Monat, den Monaten und Wochentage an. Die 5 Sterne bedeuten also: "Führe die hintenstehende Datei jede Minute, jede Stunde, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Will man in der Nacht keine schwarzen Bilder sammeln, kann man auch folgende Zeile verwenden: <pre> * 6-21 * * * /home/pi/timeshot.sh </pre> Heißt dann so viel wie: "Führe die hintenstehende Datei jede Minute, in den Stunden von 6 bis 21, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Damit ist aber nicht "von 6 bis 21 Uhr!" gemeint - es werden Bilder von 6:00 Uhr bis 21:59 Uhr aufgenommen. = Bilder verarbeiten = Fotos einfach der der Bilder aufnehmen macht natürlich wenig Sinn. Zunächst ist aber erst einmal die Frage: Wie viel Daten kommen überhaupt zusammen? In meinem Fall - jede Minute (also 1440 am Tag) ein Bild 1280x960 bei 85 % Qualität sammeln sich am Tag etwa 85 MiB an. Was macht man damit? Hier ein paar Vorschläge: == Video == Naheliegend ist natürlich, ein Video der Fotos zu erstellen. Nichts leichter als das! Das ist auch der Grund, warum sie nach dem oben angegebenen Schema durchnummeriert sind. Dateien mit diesem Schema lassen sich direkt mit [http://www.ffmpeg.org FFmpeg] verarbeiten. Ich wollte es auf dem Raspberry Pi machen, musste aber sehr schnell einsehen, dass man es schlichtweg vergessen kann, zumindest bei meinen Parametern - h.264 bei 2,5 Mbit/s Bitrate. Die ersten Bilder werden noch relativ schnell zusammengefügt, irgendwann kommt man aber deutlich unter 1 fps beim Codieren. Vermutlich scheitert es hier beim RAM und vermutlich verwendet FFmpeg den in Hardware vorhandenen h.264-Codec nicht. Der Desktop-PC hat da deutlich mehr Power. Also Bilder übertragen, in dem Ordner eine Kommandozeile öffnen und folgenden Befehl reinklöppeln: <pre> ffmpeg.exe -f image2 -i img_%04d.jpg -vcodec libx264 -vb 2500k -acodec null -r 25 day.mp4 </pre> Die Magie kommt vom Parameter -i, in dem alle Bilder mit dem Format img_%04d.jpg zusammengestückelt werden. Wer den Befehl in eine Batch-Datei stecken möchte, muss das % durch %% ersetzen, damit das "%0" nicht interpretiert wird. Allerdings gibt es ein kleines Problem: Fehlt ein Bild, wird die Erstellung dort beendet. Um diesem Problem zu gehen, habe ich ein kleines PHP-Script geschrieben, das hierfür Platzhalter einfügt: <geshi lang="php"> <?php $w = 1280; $h = 960; $name_min = 0; $name_max = 1439; $name_digits = 4; $name_format = "img_#.jpg"; $im = imagecreatetruecolor($w, $h); $col = imagecolorallocate($im, 0, 0, 255); imagefilledrectangle($im, 0, 0, $w, $h, $col); for($i = $name_min; $i <= $name_max; $i++) { $digits = str_pad($i, $name_digits, "0", STR_PAD_LEFT); $fname = str_replace("#", $digits, $name_format); if(!is_file($fname)) { echo "file " . $fname . " not found - create.\n"; imagejpeg($im, $fname, 85); } } </geshi> Das Script macht nichts anderes als Dateien mit dem Format "img_#.jpg" zu suchen, wobei # durch eine mit Nullen auf vier aufgefüllten Zahl von 0 bis 1439 ersetzt wird. Ist eine Datei nicht vorhanden, wird für diese das vorbereite Bild als JPEG geschrieben. Wer will, kann anstelle des imagefilledrectangle natürlich jeden anderen Befehl zur Bildmanipulation einsetzen. == Tagesbild == Nicht wirklich aussagekräftig, aber eine nette Spielerei, die im Prinzip ganz einfach ist: Man nimmt von jedem Einzelbild einen von der Uhrzeit abhängigen Streifen heraus und baut damit ein neues Bild, das aus (fast) allen Bildern des Tages zusammengebaut wurde. Da die 1280 Pixel Bildbreite schon relativ nah an den 1400 Bildern pro Tag sind, habe ich vertikale Streifen verwendet. Der Einfachheit halber ist das Script ebenfalls in PHP zusammengeschustert: <geshi lang="php"> <?php $folder = "/bilder/"; $dst = imagecreatetruecolor(1280, 960); $red = imagecolorallocate($dst, 255, 0, 0); imagefilledrectangle($dst, 0,0,1280,960, $red); for($i = 0; $i < 1280; $i++) { $file = $folder."/img_".str_pad($i+160, 4, "0", STR_PAD_LEFT).".jpg"; if(is_file($file)) { echo "."; $src = imagecreatefromjpeg($file); imagecopyresampled($dst, $src, $i, 0, $i, 0, 1, 1280, 1, 1280); imagedestroy($src); } else { echo "#"; } } echo "\n"; imagejpeg($dst, $folder.".jpg", 90); imagedestroy($dst); </geshi> Nicht ganz so übersichtlich wie das vorherige Script. Im Prinzip wird für jedes Bild (es wird erst ab Bild 160 eingelesen, damit es 1280 Streifen werden) ein imagecopyresampled in das Zielbild durchgeführt, wobei jeder Streifen 1 Pixel breit ist. Ursprünglich wollte ich jede Streifen 2 bzw. 3 Pixel breit machen und die die "linken" mit leicht überblenden, damit es keine harten Kanten gibt. Nur scheint das in PHP nicht so ganz trivial zu sein. Hier aber ein paar Ergebnisse der Tagesbilder: <gallery> Datei:timelapse_2013-06-14.jpg|14.06.2013 Datei:timelapse_2013-06-17.jpg|17.06.2013 Datei:timelapse_2013-06-21.jpg|21.06.2013 Datei:timelapse_2013-07-01.jpg|01.07.2013 Datei:timelapse_2013-07-09.jpg|09.07.2013 Datei:timelapse_2013-07-19.jpg|19.07.2013 Datei:timelapse_2013-07-23.jpg|23.07.2013 Datei:timelapse_2013-07-31.jpg|31.07.2013 </gallery> == Webserver == Natürlich kann man, wenn man das aktuelle Webcam-Bild auf einer Internetseite einbinden will, jede Minute mit immer gleichem Namen in den /var/www-Ordner kopieren lassen. Normalerweise sollte das Betriebssystem die Datei auch im RAM cachen. Trotzdem kann es sein, dass das Ganze unnütze Schreibzyklen auf dem Flash-Speicher erzeugt und somit für eine schnellere Alterung sorgt. Mit folgendem PHP-Script lässt sich das aktuelle Bild von einem anderen Ort im Dateisystem lesen und in den Webspace holen: <geshi lang="PHP"> <?php $img_path = "/media/usb/timelapse/#d/img_#m.jpg"; $date = date("Y-m-d"); $minute = date("H") * 60 + date("i"); $search = array("#d", "#m"); $replace = array($date, $minute); $file = str_replace($search, $replace, $img_path); header("Content-Type: Content-Type: image/jpeg"); header("Cache-Control: no-cache, must-revalidate"); if(is_file($file)) { readfile($file); } else { $w = 1280; $h = 960; $im = imagecreatetruecolor($w, $h); $col = imagecolorallocate($im, 0, 0, 255); imagefilledrectangle($im, 0, 0, $w, $h, $col); imagejpeg($im); } </geshi> Wird kein aktuelles Bild gefunden (entweder weil die Kamera Aufnahmepause hat oder es noch kein Bild gibt - Cron läuft nicht zwangsläufig mit dem Minutenumbruch), wird eine blaue Fläche ausgeliefert. Um die Bilder laden zu können, muss man aber dem Benutzer des Webservers mindestens Leserechte in den entsprechenden Ordnern geben. = Anmerkungen = Hier noch ein paar Dinge, die mir beim Betreiben der Kamera aufgefallen sind: * Auch halbwegs moderne Bildsensoren [http://hobbyelektronik.org/b/2013/06/ein-tag/ mögen keine dauerhafte Sonneneinstrahlung] * Die Logitech-Kamera oder deren Treiber stürzen ab und zu ab und reißen den kompletten Raspberry Pi herunter [[Kategorie:Software]] [[Kategorie:Linux]] [[Kategorie:Raspberry Pi]] 6d85e1018a7d3ebc2aa6bdf36a7587032ba05867 871 869 2013-12-31T15:20:31Z Chris 2 bisschen mehr sudo (bei mkdir /media/usb und blkid) darf sein wikitext text/x-wiki Was macht man mit einem stromsparenden Computer und einer Webcam? Die Frage habe ich mir genau zur letzten Lernphase meines Studiums gestellt und gleich mal auf die Probe gestellt, ob es möglich ist, innerhalb einer Mittagspause eine Zeitraffer-Kamera zu basteln (siehe auch [http://hobbyelektronik.org/b/2013/06/ein-tag/ hier]). Wenn man als Bash-Anfänger die die Dauer der Mittagspause an die südländische Siesta annähert kann ich schon vorweg sagen: Ja, es ist möglich! = Ausgangsmaterial = Als Computer kommt der Raspberry Pi zum Einsatz. Als Webcam dient eine Logitech C310. Um die SD-Karte etwas zu schonen kommt ein billiger USB-Stick zum Einsatz, der nur als Aufnahmeziel dient. = Einrichten = == Kamera == Da es sich bei der Webcam um eine mit USB-Anschluss handelt, kann sie (meines Wissens) nicht ausschließlich mit dem verwendet werden, das Raspian hergibt. Mit dem Befehl lsusb kann man herausfinden, was am USB hängt: <pre> $ lsusb Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 058f:6387 Alcor Micro Corp. Flash Drive Bus 001 Device 005: ID 046d:081b Logitech, Inc. Webcam C310 </pre> Die Webcam ist also am Computer anhängig, genauso wie der USB-Stick. Über den Befehl ls /dev/video* werden alle Geräte angezeigt, die mit dem Namen video anfangen. Wurden also Treiber für die Kamera gefunden, erscheint sie in der Ausgabe: <pre> $ ls /dev/video* /dev/video0 </pre> Weil cat /dev/video0 > foo.jpg nicht so wirklich funktioniert, muss ein Vermittler her. Ich habe gute Erfahrungen mit fswebcam gemacht. Installation und Test sehen wie folgt aus: <pre> $ sudo apt-get install fswebcam [...] $ fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 testimg.jpg </pre> Der letztere Befehl nimmt ein Bild mit der Auflösung (Parameter -r) 1280x960 auf. Das -q nach der Qualitätsstufe (hier: 85) ist Absicht - bei dem Parameter handelt es sich nicht um -q wie quality, sondern um quiet. Mit -d wird das Device gewählt und anschließend folgt die Ausgabedatei. Diese kann, sofern ein Webserver installiert ist, nach /var/www verschieben oder natürlich direkt auf dem Computer ansehen. In meinem Fall wird der Raspberry "headless" betrieben und die Datei über SSH-Filetransfer auf den Haupt-PC befördert. Funktioniert die Kamera, kann der USB-Speicher angedockt werden: == USB-Stick einbinden == Viele Wege führen bekanntlich nach Rom, genauso kann man Speicher auf verschiedene Weisen einbinden. Das hier ist eine. Zunächst muss ein Verzeichnis angelegt werden, in das der USB-Stick später eingebunden (gemountet) wird. In meinem Fall ist dies /media/usb: <pre> $ sudo mkdir /media/usb </pre> Nun muss herausgefunden werden, wie man den Speicher anspricht. Am besten verwendet man dessen [[wpde:Universally Unique Identifier|Universally Unique Identifier]] (kurz UUID). Der Vorteil an diesem ist, wie der Name schon sagt, dass er Eindeutig ist. Mit dem Befehl blkid können die UUIDs aller verfügbaren Speicher angezeigt werden: <pre> $ sudo blkid /dev/sda1: UUID="0CA5-719C" TYPE="vfat" LABEL="KINGSTON" /dev/mmcblk0p1: SEC_TYPE="msdos" UUID="C522-EA52" TYPE="vfat" /dev/mmcblk0p2: UUID="62ba9ec9-47d9-4421-aaee-71dd6c0f3707" TYPE="ext4" </pre> In geistiger Umnachtung habe ich den USB-Stick "KINGSTON" genannt, das hat allerdings keine Bedeutung. Wichtig ist das, was hinter "UUID=" steht. Man kann den Stick zwar schnell mit mount einbinden, nach dem nächsten Neustart hat man ihn aber verloren und das passiert - auch wenn das System stabil läuft - mit Sicherheit. Also muss er in die fstab (file system table) eingetragen werden. Da man mit ihr nicht spielt, muss sie mit Superuser-Rechten bearbeitet werden: <pre> $ sudo nano /etc/fstab </pre> Die bereits vorhandenen Einträge kann man ignorieren, hier muss der zu verwendende USB-Stick hinzugefügt werden. Ist dieser mit FAT formatiert und hat die UUID 0CA5-719C, kann folgende Zeile an das Ende der Datei geschrieben werden: <pre> UUID=0CA5-719C /media/usb/ vfat defaults,auto,users,noatime,umask=000,rw 0 0 </pre> Mit Strg+X Schließen und das Speichern mit Y und Druck auf die Enter-Taste bestätigen. Navigiert man unter /media/usb kann man nun wunderbar Dateien anlegen, ABER: Diese befinden sich NICHT auf dem USB-Stick! fstab wird nur beim Neustart gelesen. Also heißt es <pre> $ sudo reboot </pre> eingeben und somit die Uptime auf 0 zurücksetzen. Mit dem Befehl df kann jetzt überprüft werden, ob der Speicher richtig eingebunden wurde. Gleichzeitig sieht man auch, wie viel Speicher bereits genutzt wird: <pre> $ df Filesystem 1K-blocks Used Available Use% Mounted on rootfs 1838936 1775400 0 100% / /dev/root 1838936 1775400 0 100% / devtmpfs 110568 0 110568 0% /dev tmpfs 23768 232 23536 1% /run tmpfs 5120 0 5120 0% /run/lock tmpfs 47520 0 47520 0% /run/shm /dev/mmcblk0p1 57288 18960 38328 34% /boot /dev/sda1 4006852 1591764 2415088 40% /media/usb </pre> Der letzte Eintrag ist der interessante: /dev/sda1 ist nach /media/usb gemountet. Wenn man sich nicht sicher ist, kann man vorher von einem anderen PC eine Datei auf dem USB-Stick ablegen und mit ls /media/usb prüfen, ob diese vorhanden ist. (Es kann sein, dass man die Berechtigung auf den Mouting-Point noch anpassen muss, da der Artikels etwas später als das damalige Einrichten entstand, bin ich mir nicht absolut sicher) = Das Zeitraffer-Script = Die Kamera funktioniert, der Zusatzspeicher ist da - nun fehlt nur noch die zeitgesteuerte Aufnahme. Am einfachsten geht das über ein kleines Script, das wahlweise direkt im Benutzerordner (home) angelegt werden kann. Der schnellste Weg nach Hause führt über den Befehl cd. Über den Befehl <pre> $ nano timeshot.sh </pre> wird Nano für die (noch nicht vorhandene) Datei timeshot.sh geöffnet. Dort kann nun folgender Code eingefügt werden: <geshi lang="bash"> #!/bin/sh dt=$(date +"%Y-%m-%d") time_now=$(date +%s) time_mid=$(date -d "00:00" +%s) mins=$((($time_now-$time_mid)/60)) timestamp=`printf "%04d" $mins` dstdir=/media/usb/timelapse/$dt/ mkdir -p $dstdir fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 $dstdir/img_$timestamp.jpg </geshi> Ganz oben kommt erst einmal der Shebang, anschließend werden ein paar Variablen definiert: In der Variable dt steht das aktuelle Datum im Format "Jahr-Monat-Datum", anschließend wird in die Variablen time_now und time_mid der Unix-Timestamp (also die Sekunden seit dem 01.01.1970) für die aktuelle Zeit und Mitternacht des aktuellen Tags geschrieben. Anschließend wird die Differenz der beiden Werte berechnet und durch 60 geteilt. Mit dem Befehl `printf "%04d" $mins` wird die Zahl auf alles "vor dem Komma" abgeschnitten und auf 4 Zeichen mit Nullen gefüllt und in die Variable timestamp geschrieben. In timestamp steht also nichts anderes als die aktuelle Minute des Tages. Warum? Später mehr dazu. dstdir gibt, wie sich erahnen lässt, das Zielverzeichnis des Bildes an, wobei der Ordner in der tiefsten Ebene dem aktuellen Datum entspricht. Existiert dieses Verzeichnis nicht, wird es über mkdir angelegt. Im letzten Befehl wird das bereits bekannte Programm fswebcam aufgerufen. Der endgültige Dateiname wird hier noch zusammengebaut. Vor die Minute des Tages wird noch ein "img_" vorangestellt und noch ein ".jpg" angehängt, damit die Dateien auch einen "Nachnamen" haben. Mit Strg+X, y, Enter ist die Datei im Dateisystem, kann aber noch nicht ausgeführt werden. Über den Befehl <pre> $ chmod 766 </pre> gibt man der Datei Ausführungsrechte für den eigenen Benutzer. Führt man sie nun aus, bringt sie zumindest bei mir eine Warnung (die man aber ignorieren kann): <pre> $ ./timeshot.sh Corrupt JPEG data: 1 extraneous bytes before marker 0xd0 </pre> Damit man nun nicht jede Minute vor dem Rechner verbringen muss, ist es zumindest empfehlenswert, die Aufnahme zeitgesteuert auszuführen. Dafür gibt es unter Linux crontab (Zeitplan). Mit dem Befehl crontab -e öffnet man diesen für den aktuellen Benutzer. Ganz am Ende der Datei kann man nun folgendes eintragen: <pre> * * * * * /home/pi/timeshot.sh </pre> Was da auf den ersten Blick etwas kryptisch aussieht ist es eigentlich nicht. /home/pi/timeshot.sh deutet zumindest einmal auf die Datei hin, die ausgeführt wird. Die Sterne vorne sind Wildcards, und bedeutet so viel wie "jede". In Cron gibt man vorne die Ausführung für die Minuten, Stunden, Tage im Monat, den Monaten und Wochentage an. Die 5 Sterne bedeuten also: "Führe die hintenstehende Datei jede Minute, jede Stunde, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Will man in der Nacht keine schwarzen Bilder sammeln, kann man auch folgende Zeile verwenden: <pre> * 6-21 * * * /home/pi/timeshot.sh </pre> Heißt dann so viel wie: "Führe die hintenstehende Datei jede Minute, in den Stunden von 6 bis 21, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Damit ist aber nicht "von 6 bis 21 Uhr!" gemeint - es werden Bilder von 6:00 Uhr bis 21:59 Uhr aufgenommen. = Bilder verarbeiten = Fotos einfach der der Bilder aufnehmen macht natürlich wenig Sinn. Zunächst ist aber erst einmal die Frage: Wie viel Daten kommen überhaupt zusammen? In meinem Fall - jede Minute (also 1440 am Tag) ein Bild 1280x960 bei 85 % Qualität sammeln sich am Tag etwa 85 MiB an. Was macht man damit? Hier ein paar Vorschläge: == Video == Naheliegend ist natürlich, ein Video der Fotos zu erstellen. Nichts leichter als das! Das ist auch der Grund, warum sie nach dem oben angegebenen Schema durchnummeriert sind. Dateien mit diesem Schema lassen sich direkt mit [http://www.ffmpeg.org FFmpeg] verarbeiten. Ich wollte es auf dem Raspberry Pi machen, musste aber sehr schnell einsehen, dass man es schlichtweg vergessen kann, zumindest bei meinen Parametern - h.264 bei 2,5 Mbit/s Bitrate. Die ersten Bilder werden noch relativ schnell zusammengefügt, irgendwann kommt man aber deutlich unter 1 fps beim Codieren. Vermutlich scheitert es hier beim RAM und vermutlich verwendet FFmpeg den in Hardware vorhandenen h.264-Codec nicht. Der Desktop-PC hat da deutlich mehr Power. Also Bilder übertragen, in dem Ordner eine Kommandozeile öffnen und folgenden Befehl reinklöppeln: <pre> ffmpeg.exe -f image2 -i img_%04d.jpg -vcodec libx264 -vb 2500k -acodec null -r 25 day.mp4 </pre> Die Magie kommt vom Parameter -i, in dem alle Bilder mit dem Format img_%04d.jpg zusammengestückelt werden. Wer den Befehl in eine Batch-Datei stecken möchte, muss das % durch %% ersetzen, damit das "%0" nicht interpretiert wird. Allerdings gibt es ein kleines Problem: Fehlt ein Bild, wird die Erstellung dort beendet. Um diesem Problem zu gehen, habe ich ein kleines PHP-Script geschrieben, das hierfür Platzhalter einfügt: <geshi lang="php"> <?php $w = 1280; $h = 960; $name_min = 0; $name_max = 1439; $name_digits = 4; $name_format = "img_#.jpg"; $im = imagecreatetruecolor($w, $h); $col = imagecolorallocate($im, 0, 0, 255); imagefilledrectangle($im, 0, 0, $w, $h, $col); for($i = $name_min; $i <= $name_max; $i++) { $digits = str_pad($i, $name_digits, "0", STR_PAD_LEFT); $fname = str_replace("#", $digits, $name_format); if(!is_file($fname)) { echo "file " . $fname . " not found - create.\n"; imagejpeg($im, $fname, 85); } } </geshi> Das Script macht nichts anderes als Dateien mit dem Format "img_#.jpg" zu suchen, wobei # durch eine mit Nullen auf vier aufgefüllten Zahl von 0 bis 1439 ersetzt wird. Ist eine Datei nicht vorhanden, wird für diese das vorbereite Bild als JPEG geschrieben. Wer will, kann anstelle des imagefilledrectangle natürlich jeden anderen Befehl zur Bildmanipulation einsetzen. == Tagesbild == Nicht wirklich aussagekräftig, aber eine nette Spielerei, die im Prinzip ganz einfach ist: Man nimmt von jedem Einzelbild einen von der Uhrzeit abhängigen Streifen heraus und baut damit ein neues Bild, das aus (fast) allen Bildern des Tages zusammengebaut wurde. Da die 1280 Pixel Bildbreite schon relativ nah an den 1400 Bildern pro Tag sind, habe ich vertikale Streifen verwendet. Der Einfachheit halber ist das Script ebenfalls in PHP zusammengeschustert: <geshi lang="php"> <?php $folder = "/bilder/"; $dst = imagecreatetruecolor(1280, 960); $red = imagecolorallocate($dst, 255, 0, 0); imagefilledrectangle($dst, 0,0,1280,960, $red); for($i = 0; $i < 1280; $i++) { $file = $folder."/img_".str_pad($i+160, 4, "0", STR_PAD_LEFT).".jpg"; if(is_file($file)) { echo "."; $src = imagecreatefromjpeg($file); imagecopyresampled($dst, $src, $i, 0, $i, 0, 1, 1280, 1, 1280); imagedestroy($src); } else { echo "#"; } } echo "\n"; imagejpeg($dst, $folder.".jpg", 90); imagedestroy($dst); </geshi> Nicht ganz so übersichtlich wie das vorherige Script. Im Prinzip wird für jedes Bild (es wird erst ab Bild 160 eingelesen, damit es 1280 Streifen werden) ein imagecopyresampled in das Zielbild durchgeführt, wobei jeder Streifen 1 Pixel breit ist. Ursprünglich wollte ich jede Streifen 2 bzw. 3 Pixel breit machen und die die "linken" mit leicht überblenden, damit es keine harten Kanten gibt. Nur scheint das in PHP nicht so ganz trivial zu sein. Hier aber ein paar Ergebnisse der Tagesbilder: <gallery> Datei:timelapse_2013-06-14.jpg|14.06.2013 Datei:timelapse_2013-06-17.jpg|17.06.2013 Datei:timelapse_2013-06-21.jpg|21.06.2013 Datei:timelapse_2013-07-01.jpg|01.07.2013 Datei:timelapse_2013-07-09.jpg|09.07.2013 Datei:timelapse_2013-07-19.jpg|19.07.2013 Datei:timelapse_2013-07-23.jpg|23.07.2013 Datei:timelapse_2013-07-31.jpg|31.07.2013 </gallery> == Webserver == Natürlich kann man, wenn man das aktuelle Webcam-Bild auf einer Internetseite einbinden will, jede Minute mit immer gleichem Namen in den /var/www-Ordner kopieren lassen. Normalerweise sollte das Betriebssystem die Datei auch im RAM cachen. Trotzdem kann es sein, dass das Ganze unnütze Schreibzyklen auf dem Flash-Speicher erzeugt und somit für eine schnellere Alterung sorgt. Mit folgendem PHP-Script lässt sich das aktuelle Bild von einem anderen Ort im Dateisystem lesen und in den Webspace holen: <geshi lang="PHP"> <?php $img_path = "/media/usb/timelapse/#d/img_#m.jpg"; $date = date("Y-m-d"); $minute = date("H") * 60 + date("i"); $search = array("#d", "#m"); $replace = array($date, $minute); $file = str_replace($search, $replace, $img_path); header("Content-Type: Content-Type: image/jpeg"); header("Cache-Control: no-cache, must-revalidate"); if(is_file($file)) { readfile($file); } else { $w = 1280; $h = 960; $im = imagecreatetruecolor($w, $h); $col = imagecolorallocate($im, 0, 0, 255); imagefilledrectangle($im, 0, 0, $w, $h, $col); imagejpeg($im); } </geshi> Wird kein aktuelles Bild gefunden (entweder weil die Kamera Aufnahmepause hat oder es noch kein Bild gibt - Cron läuft nicht zwangsläufig mit dem Minutenumbruch), wird eine blaue Fläche ausgeliefert. Um die Bilder laden zu können, muss man aber dem Benutzer des Webservers mindestens Leserechte in den entsprechenden Ordnern geben. = Anmerkungen = Hier noch ein paar Dinge, die mir beim Betreiben der Kamera aufgefallen sind: * Auch halbwegs moderne Bildsensoren [http://hobbyelektronik.org/b/2013/06/ein-tag/ mögen keine dauerhafte Sonneneinstrahlung] * Die Logitech-Kamera oder deren Treiber stürzen ab und zu ab und reißen den kompletten Raspberry Pi herunter [[Kategorie:Software]] [[Kategorie:Linux]] [[Kategorie:Raspberry Pi]] cc626db62c682b3d26438c17b5c26e929dbe9b54 872 871 2013-12-31T15:23:02Z Chris 2 /* Anmerkungen */ Info zu den Abstürzen wikitext text/x-wiki Was macht man mit einem stromsparenden Computer und einer Webcam? Die Frage habe ich mir genau zur letzten Lernphase meines Studiums gestellt und gleich mal auf die Probe gestellt, ob es möglich ist, innerhalb einer Mittagspause eine Zeitraffer-Kamera zu basteln (siehe auch [http://hobbyelektronik.org/b/2013/06/ein-tag/ hier]). Wenn man als Bash-Anfänger die die Dauer der Mittagspause an die südländische Siesta annähert kann ich schon vorweg sagen: Ja, es ist möglich! = Ausgangsmaterial = Als Computer kommt der Raspberry Pi zum Einsatz. Als Webcam dient eine Logitech C310. Um die SD-Karte etwas zu schonen kommt ein billiger USB-Stick zum Einsatz, der nur als Aufnahmeziel dient. = Einrichten = == Kamera == Da es sich bei der Webcam um eine mit USB-Anschluss handelt, kann sie (meines Wissens) nicht ausschließlich mit dem verwendet werden, das Raspian hergibt. Mit dem Befehl lsusb kann man herausfinden, was am USB hängt: <pre> $ lsusb Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 058f:6387 Alcor Micro Corp. Flash Drive Bus 001 Device 005: ID 046d:081b Logitech, Inc. Webcam C310 </pre> Die Webcam ist also am Computer anhängig, genauso wie der USB-Stick. Über den Befehl ls /dev/video* werden alle Geräte angezeigt, die mit dem Namen video anfangen. Wurden also Treiber für die Kamera gefunden, erscheint sie in der Ausgabe: <pre> $ ls /dev/video* /dev/video0 </pre> Weil cat /dev/video0 > foo.jpg nicht so wirklich funktioniert, muss ein Vermittler her. Ich habe gute Erfahrungen mit fswebcam gemacht. Installation und Test sehen wie folgt aus: <pre> $ sudo apt-get install fswebcam [...] $ fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 testimg.jpg </pre> Der letztere Befehl nimmt ein Bild mit der Auflösung (Parameter -r) 1280x960 auf. Das -q nach der Qualitätsstufe (hier: 85) ist Absicht - bei dem Parameter handelt es sich nicht um -q wie quality, sondern um quiet. Mit -d wird das Device gewählt und anschließend folgt die Ausgabedatei. Diese kann, sofern ein Webserver installiert ist, nach /var/www verschieben oder natürlich direkt auf dem Computer ansehen. In meinem Fall wird der Raspberry "headless" betrieben und die Datei über SSH-Filetransfer auf den Haupt-PC befördert. Funktioniert die Kamera, kann der USB-Speicher angedockt werden: == USB-Stick einbinden == Viele Wege führen bekanntlich nach Rom, genauso kann man Speicher auf verschiedene Weisen einbinden. Das hier ist eine. Zunächst muss ein Verzeichnis angelegt werden, in das der USB-Stick später eingebunden (gemountet) wird. In meinem Fall ist dies /media/usb: <pre> $ sudo mkdir /media/usb </pre> Nun muss herausgefunden werden, wie man den Speicher anspricht. Am besten verwendet man dessen [[wpde:Universally Unique Identifier|Universally Unique Identifier]] (kurz UUID). Der Vorteil an diesem ist, wie der Name schon sagt, dass er Eindeutig ist. Mit dem Befehl blkid können die UUIDs aller verfügbaren Speicher angezeigt werden: <pre> $ sudo blkid /dev/sda1: UUID="0CA5-719C" TYPE="vfat" LABEL="KINGSTON" /dev/mmcblk0p1: SEC_TYPE="msdos" UUID="C522-EA52" TYPE="vfat" /dev/mmcblk0p2: UUID="62ba9ec9-47d9-4421-aaee-71dd6c0f3707" TYPE="ext4" </pre> In geistiger Umnachtung habe ich den USB-Stick "KINGSTON" genannt, das hat allerdings keine Bedeutung. Wichtig ist das, was hinter "UUID=" steht. Man kann den Stick zwar schnell mit mount einbinden, nach dem nächsten Neustart hat man ihn aber verloren und das passiert - auch wenn das System stabil läuft - mit Sicherheit. Also muss er in die fstab (file system table) eingetragen werden. Da man mit ihr nicht spielt, muss sie mit Superuser-Rechten bearbeitet werden: <pre> $ sudo nano /etc/fstab </pre> Die bereits vorhandenen Einträge kann man ignorieren, hier muss der zu verwendende USB-Stick hinzugefügt werden. Ist dieser mit FAT formatiert und hat die UUID 0CA5-719C, kann folgende Zeile an das Ende der Datei geschrieben werden: <pre> UUID=0CA5-719C /media/usb/ vfat defaults,auto,users,noatime,umask=000,rw 0 0 </pre> Mit Strg+X Schließen und das Speichern mit Y und Druck auf die Enter-Taste bestätigen. Navigiert man unter /media/usb kann man nun wunderbar Dateien anlegen, ABER: Diese befinden sich NICHT auf dem USB-Stick! fstab wird nur beim Neustart gelesen. Also heißt es <pre> $ sudo reboot </pre> eingeben und somit die Uptime auf 0 zurücksetzen. Mit dem Befehl df kann jetzt überprüft werden, ob der Speicher richtig eingebunden wurde. Gleichzeitig sieht man auch, wie viel Speicher bereits genutzt wird: <pre> $ df Filesystem 1K-blocks Used Available Use% Mounted on rootfs 1838936 1775400 0 100% / /dev/root 1838936 1775400 0 100% / devtmpfs 110568 0 110568 0% /dev tmpfs 23768 232 23536 1% /run tmpfs 5120 0 5120 0% /run/lock tmpfs 47520 0 47520 0% /run/shm /dev/mmcblk0p1 57288 18960 38328 34% /boot /dev/sda1 4006852 1591764 2415088 40% /media/usb </pre> Der letzte Eintrag ist der interessante: /dev/sda1 ist nach /media/usb gemountet. Wenn man sich nicht sicher ist, kann man vorher von einem anderen PC eine Datei auf dem USB-Stick ablegen und mit ls /media/usb prüfen, ob diese vorhanden ist. (Es kann sein, dass man die Berechtigung auf den Mouting-Point noch anpassen muss, da der Artikels etwas später als das damalige Einrichten entstand, bin ich mir nicht absolut sicher) = Das Zeitraffer-Script = Die Kamera funktioniert, der Zusatzspeicher ist da - nun fehlt nur noch die zeitgesteuerte Aufnahme. Am einfachsten geht das über ein kleines Script, das wahlweise direkt im Benutzerordner (home) angelegt werden kann. Der schnellste Weg nach Hause führt über den Befehl cd. Über den Befehl <pre> $ nano timeshot.sh </pre> wird Nano für die (noch nicht vorhandene) Datei timeshot.sh geöffnet. Dort kann nun folgender Code eingefügt werden: <geshi lang="bash"> #!/bin/sh dt=$(date +"%Y-%m-%d") time_now=$(date +%s) time_mid=$(date -d "00:00" +%s) mins=$((($time_now-$time_mid)/60)) timestamp=`printf "%04d" $mins` dstdir=/media/usb/timelapse/$dt/ mkdir -p $dstdir fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 $dstdir/img_$timestamp.jpg </geshi> Ganz oben kommt erst einmal der Shebang, anschließend werden ein paar Variablen definiert: In der Variable dt steht das aktuelle Datum im Format "Jahr-Monat-Datum", anschließend wird in die Variablen time_now und time_mid der Unix-Timestamp (also die Sekunden seit dem 01.01.1970) für die aktuelle Zeit und Mitternacht des aktuellen Tags geschrieben. Anschließend wird die Differenz der beiden Werte berechnet und durch 60 geteilt. Mit dem Befehl `printf "%04d" $mins` wird die Zahl auf alles "vor dem Komma" abgeschnitten und auf 4 Zeichen mit Nullen gefüllt und in die Variable timestamp geschrieben. In timestamp steht also nichts anderes als die aktuelle Minute des Tages. Warum? Später mehr dazu. dstdir gibt, wie sich erahnen lässt, das Zielverzeichnis des Bildes an, wobei der Ordner in der tiefsten Ebene dem aktuellen Datum entspricht. Existiert dieses Verzeichnis nicht, wird es über mkdir angelegt. Im letzten Befehl wird das bereits bekannte Programm fswebcam aufgerufen. Der endgültige Dateiname wird hier noch zusammengebaut. Vor die Minute des Tages wird noch ein "img_" vorangestellt und noch ein ".jpg" angehängt, damit die Dateien auch einen "Nachnamen" haben. Mit Strg+X, y, Enter ist die Datei im Dateisystem, kann aber noch nicht ausgeführt werden. Über den Befehl <pre> $ chmod 766 </pre> gibt man der Datei Ausführungsrechte für den eigenen Benutzer. Führt man sie nun aus, bringt sie zumindest bei mir eine Warnung (die man aber ignorieren kann): <pre> $ ./timeshot.sh Corrupt JPEG data: 1 extraneous bytes before marker 0xd0 </pre> Damit man nun nicht jede Minute vor dem Rechner verbringen muss, ist es zumindest empfehlenswert, die Aufnahme zeitgesteuert auszuführen. Dafür gibt es unter Linux crontab (Zeitplan). Mit dem Befehl crontab -e öffnet man diesen für den aktuellen Benutzer. Ganz am Ende der Datei kann man nun folgendes eintragen: <pre> * * * * * /home/pi/timeshot.sh </pre> Was da auf den ersten Blick etwas kryptisch aussieht ist es eigentlich nicht. /home/pi/timeshot.sh deutet zumindest einmal auf die Datei hin, die ausgeführt wird. Die Sterne vorne sind Wildcards, und bedeutet so viel wie "jede". In Cron gibt man vorne die Ausführung für die Minuten, Stunden, Tage im Monat, den Monaten und Wochentage an. Die 5 Sterne bedeuten also: "Führe die hintenstehende Datei jede Minute, jede Stunde, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Will man in der Nacht keine schwarzen Bilder sammeln, kann man auch folgende Zeile verwenden: <pre> * 6-21 * * * /home/pi/timeshot.sh </pre> Heißt dann so viel wie: "Führe die hintenstehende Datei jede Minute, in den Stunden von 6 bis 21, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Damit ist aber nicht "von 6 bis 21 Uhr!" gemeint - es werden Bilder von 6:00 Uhr bis 21:59 Uhr aufgenommen. = Bilder verarbeiten = Fotos einfach der der Bilder aufnehmen macht natürlich wenig Sinn. Zunächst ist aber erst einmal die Frage: Wie viel Daten kommen überhaupt zusammen? In meinem Fall - jede Minute (also 1440 am Tag) ein Bild 1280x960 bei 85 % Qualität sammeln sich am Tag etwa 85 MiB an. Was macht man damit? Hier ein paar Vorschläge: == Video == Naheliegend ist natürlich, ein Video der Fotos zu erstellen. Nichts leichter als das! Das ist auch der Grund, warum sie nach dem oben angegebenen Schema durchnummeriert sind. Dateien mit diesem Schema lassen sich direkt mit [http://www.ffmpeg.org FFmpeg] verarbeiten. Ich wollte es auf dem Raspberry Pi machen, musste aber sehr schnell einsehen, dass man es schlichtweg vergessen kann, zumindest bei meinen Parametern - h.264 bei 2,5 Mbit/s Bitrate. Die ersten Bilder werden noch relativ schnell zusammengefügt, irgendwann kommt man aber deutlich unter 1 fps beim Codieren. Vermutlich scheitert es hier beim RAM und vermutlich verwendet FFmpeg den in Hardware vorhandenen h.264-Codec nicht. Der Desktop-PC hat da deutlich mehr Power. Also Bilder übertragen, in dem Ordner eine Kommandozeile öffnen und folgenden Befehl reinklöppeln: <pre> ffmpeg.exe -f image2 -i img_%04d.jpg -vcodec libx264 -vb 2500k -acodec null -r 25 day.mp4 </pre> Die Magie kommt vom Parameter -i, in dem alle Bilder mit dem Format img_%04d.jpg zusammengestückelt werden. Wer den Befehl in eine Batch-Datei stecken möchte, muss das % durch %% ersetzen, damit das "%0" nicht interpretiert wird. Allerdings gibt es ein kleines Problem: Fehlt ein Bild, wird die Erstellung dort beendet. Um diesem Problem zu gehen, habe ich ein kleines PHP-Script geschrieben, das hierfür Platzhalter einfügt: <geshi lang="php"> <?php $w = 1280; $h = 960; $name_min = 0; $name_max = 1439; $name_digits = 4; $name_format = "img_#.jpg"; $im = imagecreatetruecolor($w, $h); $col = imagecolorallocate($im, 0, 0, 255); imagefilledrectangle($im, 0, 0, $w, $h, $col); for($i = $name_min; $i <= $name_max; $i++) { $digits = str_pad($i, $name_digits, "0", STR_PAD_LEFT); $fname = str_replace("#", $digits, $name_format); if(!is_file($fname)) { echo "file " . $fname . " not found - create.\n"; imagejpeg($im, $fname, 85); } } </geshi> Das Script macht nichts anderes als Dateien mit dem Format "img_#.jpg" zu suchen, wobei # durch eine mit Nullen auf vier aufgefüllten Zahl von 0 bis 1439 ersetzt wird. Ist eine Datei nicht vorhanden, wird für diese das vorbereite Bild als JPEG geschrieben. Wer will, kann anstelle des imagefilledrectangle natürlich jeden anderen Befehl zur Bildmanipulation einsetzen. == Tagesbild == Nicht wirklich aussagekräftig, aber eine nette Spielerei, die im Prinzip ganz einfach ist: Man nimmt von jedem Einzelbild einen von der Uhrzeit abhängigen Streifen heraus und baut damit ein neues Bild, das aus (fast) allen Bildern des Tages zusammengebaut wurde. Da die 1280 Pixel Bildbreite schon relativ nah an den 1400 Bildern pro Tag sind, habe ich vertikale Streifen verwendet. Der Einfachheit halber ist das Script ebenfalls in PHP zusammengeschustert: <geshi lang="php"> <?php $folder = "/bilder/"; $dst = imagecreatetruecolor(1280, 960); $red = imagecolorallocate($dst, 255, 0, 0); imagefilledrectangle($dst, 0,0,1280,960, $red); for($i = 0; $i < 1280; $i++) { $file = $folder."/img_".str_pad($i+160, 4, "0", STR_PAD_LEFT).".jpg"; if(is_file($file)) { echo "."; $src = imagecreatefromjpeg($file); imagecopyresampled($dst, $src, $i, 0, $i, 0, 1, 1280, 1, 1280); imagedestroy($src); } else { echo "#"; } } echo "\n"; imagejpeg($dst, $folder.".jpg", 90); imagedestroy($dst); </geshi> Nicht ganz so übersichtlich wie das vorherige Script. Im Prinzip wird für jedes Bild (es wird erst ab Bild 160 eingelesen, damit es 1280 Streifen werden) ein imagecopyresampled in das Zielbild durchgeführt, wobei jeder Streifen 1 Pixel breit ist. Ursprünglich wollte ich jede Streifen 2 bzw. 3 Pixel breit machen und die die "linken" mit leicht überblenden, damit es keine harten Kanten gibt. Nur scheint das in PHP nicht so ganz trivial zu sein. Hier aber ein paar Ergebnisse der Tagesbilder: <gallery> Datei:timelapse_2013-06-14.jpg|14.06.2013 Datei:timelapse_2013-06-17.jpg|17.06.2013 Datei:timelapse_2013-06-21.jpg|21.06.2013 Datei:timelapse_2013-07-01.jpg|01.07.2013 Datei:timelapse_2013-07-09.jpg|09.07.2013 Datei:timelapse_2013-07-19.jpg|19.07.2013 Datei:timelapse_2013-07-23.jpg|23.07.2013 Datei:timelapse_2013-07-31.jpg|31.07.2013 </gallery> == Webserver == Natürlich kann man, wenn man das aktuelle Webcam-Bild auf einer Internetseite einbinden will, jede Minute mit immer gleichem Namen in den /var/www-Ordner kopieren lassen. Normalerweise sollte das Betriebssystem die Datei auch im RAM cachen. Trotzdem kann es sein, dass das Ganze unnütze Schreibzyklen auf dem Flash-Speicher erzeugt und somit für eine schnellere Alterung sorgt. Mit folgendem PHP-Script lässt sich das aktuelle Bild von einem anderen Ort im Dateisystem lesen und in den Webspace holen: <geshi lang="PHP"> <?php $img_path = "/media/usb/timelapse/#d/img_#m.jpg"; $date = date("Y-m-d"); $minute = date("H") * 60 + date("i"); $search = array("#d", "#m"); $replace = array($date, $minute); $file = str_replace($search, $replace, $img_path); header("Content-Type: Content-Type: image/jpeg"); header("Cache-Control: no-cache, must-revalidate"); if(is_file($file)) { readfile($file); } else { $w = 1280; $h = 960; $im = imagecreatetruecolor($w, $h); $col = imagecolorallocate($im, 0, 0, 255); imagefilledrectangle($im, 0, 0, $w, $h, $col); imagejpeg($im); } </geshi> Wird kein aktuelles Bild gefunden (entweder weil die Kamera Aufnahmepause hat oder es noch kein Bild gibt - Cron läuft nicht zwangsläufig mit dem Minutenumbruch), wird eine blaue Fläche ausgeliefert. Um die Bilder laden zu können, muss man aber dem Benutzer des Webservers mindestens Leserechte in den entsprechenden Ordnern geben. = Anmerkungen = Hier noch ein paar Dinge, die mir beim Betreiben der Kamera aufgefallen sind: * Auch halbwegs moderne Bildsensoren [http://hobbyelektronik.org/b/2013/06/ein-tag/ mögen keine dauerhafte Sonneneinstrahlung] * <strike>Die Logitech-Kamera oder deren Treiber stürzen ab und zu ab und reißen den kompletten Raspberry Pi herunter.</strike> * Schuld ist wohl die [http://hobbyelektronik.org/b/2013/12/warum-der-pi-abschmiert/ Netzwerkkarte]. sudo rpi-update hilft, löst das Problem aber nicht vollständig. [[Kategorie:Software]] [[Kategorie:Linux]] [[Kategorie:Raspberry Pi]] 3425fe9eeac796fd5a1258b9d98663026464b186 Datei:Timelapse 2013-06-14.jpg 6 347 860 2013-11-10T15:53:21Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Timelapse 2013-06-17.jpg 6 348 861 2013-11-10T15:53:22Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Timelapse 2013-06-21.jpg 6 349 862 2013-11-10T15:53:23Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Timelapse 2013-07-01.jpg 6 350 863 2013-11-10T15:53:24Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Timelapse 2013-07-09.jpg 6 351 864 2013-11-10T15:53:25Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Timelapse 2013-07-19.jpg 6 352 865 2013-11-10T15:53:26Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Timelapse 2013-07-23.jpg 6 353 866 2013-11-10T15:53:27Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Timelapse 2013-07-31.jpg 6 354 867 2013-11-10T15:53:28Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Simplecon.png 6 355 873 2014-02-02T21:16:21Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Simplecon.jpg 6 356 874 2014-02-02T21:16:55Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 EAGLE-Bibliotheken 0 358 876 2014-02-02T21:35:08Z Chris 2 Simplecon muss den Anfang machen wikitext text/x-wiki Über die Zeit sind bei mir einige Bibliotheken für EAGLE entstanden. Damit sie nicht nur auf meiner Festplatte ihr Dasein fristen und dem ein oder anderen die Arbeit erleichtern, hier zukünftig tendenziell wachsende Auswahl meiner Libs: = Konnektoren = == Simplecon == Mit dieser Bibliothek können Stiftleisten an der Kante platziert werden. Die Pads sind versetzt angeordnet, sodass sich sowohl doppelreihige Stiftleisten mit 2,54 mm Rastermaß, als auch Flachbandkabel mit 1,27 mm Rastermaß direkt anlöten lassen. Mit geeignet dünnem Leiterplattenmaterial (1 mm) lassen sich sogar Pfostensteckverbinder anlöten. In der Library sind momentan Verbinder von 2x3 bis 2x7 angelegt. <gallery> Datei:Simplecon.png|Beispiel 3x2 Datei:Simplecon.jpg|3x2 mit Steckerleiste und Flachbandkabel </gallery> Achtung: im zweiten Bild ist die Anordnung noch gespiegelt, in der Library ist die Anordnung so, dass die Pin 1-Markierung angelöteter Stecker richtig ist. [[Simplecon.zip]] [[Kategorie:Sonstiges]] 4ea12bd117098fdc6c7320461394d703b3c13f0b 878 876 2014-02-02T21:37:38Z Chris 2 wikitext text/x-wiki Über die Zeit sind bei mir einige Bibliotheken für EAGLE entstanden. Damit sie nicht nur auf meiner Festplatte ihr Dasein fristen und dem ein oder anderen die Arbeit erleichtern, hier zukünftig tendenziell wachsende Auswahl meiner Libs: = Konnektoren = == Simplecon == Mit dieser Bibliothek können Stiftleisten an der Kante platziert werden. Die Pads sind versetzt angeordnet, sodass sich sowohl doppelreihige Stiftleisten mit 2,54 mm Rastermaß, als auch Flachbandkabel mit 1,27 mm Rastermaß direkt anlöten lassen. Mit geeignet dünnem Leiterplattenmaterial (1 mm) lassen sich sogar Pfostensteckverbinder anlöten. In der Library sind momentan Verbinder von 2x3 bis 2x7 angelegt. <gallery> Datei:Simplecon.png|Beispiel 3x2 Datei:Simplecon.jpg|3x2 mit Steckerleiste und Flachbandkabel </gallery> Achtung: im zweiten Bild ist die Anordnung noch gespiegelt, in der Library ist die Anordnung so, dass die Pin 1-Markierung angelöteter Stecker richtig ist. [[Simplecon.zip]] [[Kategorie:Sonstiges]] [[Kategorie:EAGLE]] ce1f37f20ba75c34f254dda37523c1667d97ee62 Datei:Simplecon.zip 6 359 877 2014-02-02T21:36:52Z Qsysopr 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Testseite 0 2 881 661 2014-02-09T14:11:47Z Chris 2 wikitext text/x-wiki {{Infobox AVR | Typ = AtMega Schießmichtot | Takt = 42 | FuseH = 0xFF | FuseL = 0xFF }} :<math>\int_{0}^{42} \frac{23}{42}x^{2} dx</math> <math>\int_{0}^{42} \frac{23}{42}x^{2} dx</math> Testseite, für interne Verwendung. <syntaxhighlight lang="php"> <?php ladida(); $var = fopen("foobar"); ?> </syntaxhighlight> [[Datei:Xkcd.png]] [[Datei:Xkcd.png|thumb]] [[Category:Elektronik]] 0390b71007950328a65ddadf9d3865f147e13002 Datei:ZD-939L Regler.JPG 6 360 882 2014-05-10T19:06:24Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:ZD-939L Innenleben.jpg 6 361 883 2014-05-10T19:06:27Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:ZD-939L Hinweis.JPG 6 362 884 2014-05-10T19:06:29Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:ZD-939L Front umgebaut.JPG 6 363 885 2014-05-10T19:06:32Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:ZD-939L Elektronik vorne.JPG 6 364 886 2014-05-10T19:06:35Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:ZD-939L Logic-Analyzer.png 6 365 887 2014-05-10T19:34:59Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:ZD-939L J-EXT.zip 6 366 888 2014-05-10T19:54:45Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Kühlung für Zhongdi ZD-939L 0 367 889 2014-05-10T19:57:12Z Chris 2 Seite erstellt wikitext text/x-wiki Vor geraumer Zeit hab ich mir eine Zhondi ZD-393L auf den Basteltisch gestellt. Diese ist gerade beim Entlöten von SMD-Bauteilen ein sehr nützlicher Helfer. [[Datei:ZD-939L Hinweis.JPG|thumb|Aufkleber als Workaround]] Eines hat mich allerdings vom ersten Tag weg gestört: sie hat keinen Nachlauf zum Kühlen des Heizelements. Als "Workaround" hat der Importeur lediglich einen Hinweis angebracht, dass man vor dem Abschalten auf die Mindesttemperatur herunterdrehen und eine Minute warten solle. Mit dem Warten kann ich leben, allerdings ist das Einstellen der Temperatur etwas nervig: Minus-Taster drücken und halten und sich für jedes Grad einen Pieps anhören. Nur um beim Nächsten Einschalten genau das Gegenteil zu machen. selbstverständlich ebenfalls mit akustischer Untermalung. Dabei gibt es die Heißluft-Station (neben der Version mit Nachlauf) auch mit dienen Schalter fürs Heizelement. Warum hat das meine nicht? Es wird höchste Zeit, dass sich das ändert. =Analyse= [[Datei:ZD-939L_Innenleben.jpg|thumb|Blick auf die hintere Leiterkarte]] Auf das Ding und reingeschaut. Die Elektronik ist auf 3 Leiterkarten verteilt - hinten befindet sich ein teilbestücktes Board auf das die Netzleitung führt. Nachdem sich nichts darauf befindet, das auf Regelung hindeutet, dürfte es der Leistungsteil sein. Vorne im Gehäuse findet sich neben der Leiterkarte mit den Tastern vom Frontpanel auch die Platine mit dem Display. Die 3 schwarzen Vielbeiner darauf lassen erahnen: hier wird höchstwahrscheinlich geregelt. Heizung abdrehen könnte man nun sowohl auf der Leistungs- als auch der mutmaßlichen Reglerplatine. Man könnte natürlich auch direkt in die Leitung zum Heizelement eingreifen - aber warum sich die Finger an 230 V verbrennen, wenn man es auch einfacher und sicher haben kann? Ein genauerer Blick auf die Display-Platine kann also nicht schaden: <gallery> Datei:ZD-939L_Regler.JPG|Die Reglerplatine </gallery> Der 8-beinige Chip links ist ein LM358, also ein Operationsverstärker. Beim mittleren Chip im TQFP-Gehäuse handelt es sich um einen Silabs C8051F310 - einem Mikrocontroller. Rechts im Bild befindet sich ein Holtek HT1621B. Holtek kennt man auch als Mikrocontroller-Hersteller - aber zwei Mikrocontroller für einen einfachen Regler? Nicht ganz. Der Holtek ist lediglich ein LCD-Controller, was auch die Leiterbahnen zu ihm erklärt. Die Regelung übernimmt alleinig der Silabs-Chip. Interessanter als die Regelung und das Display ist für den Umbau, über welche Anschlüsse die Heizung angesteuert wird. Drei der vier Stiftleisten sind mit der Platine hinten verbunden. Die 4-polige Stiftleiste links im Bild führt zur Taster-Platine und fällt damit schon mal weg. Die untere zweipolige Stifleiste ist ein Kandidat - nachdem sie aber verdächtig nahe am LM358, ein paar diskreten Bauteilen und einem Poti liegt, dürfte es sich um den Anschluss für den Temperaturfühler sein. Alle Leitungen außer dieser verbunden bestätigt den Verdacht: Keine Temperaturanzeige. Bleiben nur noch zwei. Die links obere sieht verdächtig nach Stromversorgung aus: etwas dickere Leiterbahnen, Dioden und Kondensatoren. Nicht zuletzt ein 78L05. Warum aber 3 Pins? Eingangsspannung, Masse und Ausgangsspannung? Nein, vermutlich handelt es sich um eine symmetrische Versorgung - entweder fürs Display oder den Operationsverstärker. Ein Blick in den hinteren Teil der Lötstation bestätigt es: Ein Trafo mit Mittelabzapfung. Die Heizung muss also von der Stiftleiste rechts oben angesteuert werden. Am Stecker hängen zwei Drähte, was die Sache leichter macht. Masse lässt sich durchpiepsen und damit ist auch der Ausgang gefunden. Muss nur noch geklärt werden, wann welche Spannung anliegt und ob man einfach so einen Schalter einbringen kann. Multimeter angehängt und den Aparillo losbrummen lassen: 5V, wenn die Heizung an ist. Um sicherzustellen, dass die 5V berührungssicher sind, schnell gegen das Gehäuse, das mit PE verbunden ist: 0V, also galvanisch getrennt. Ausgezeichnet! =Umbau= Ein Ort für den zusätzlichen Schalter ist schnell gefunden: Neben dem Hauptschalter ist noch Platz. Der Akkuschrauber leiert ein Loch in die Platte und der Schalter ist drin. Für die elektrische Verbindung habe ich die Leitung zum "Backpanel" aufgetrennt und den Schalter einfach eingefügt. Da ich die Schaltung dahinter nicht genauer ansehen wollte, habe ich mich für die sicherere Ansteuerung entschlossen - theoretisch könnte man einfach eine der Leitungen auftrennen und den Schalter einfügen. Allerdings bekommt dann die Schaltung "hinten" entweder das Signal vom Mikrocontroller oder floatet durch die Gegend. Da das nicht besonders toll ist, wechselt der Schalter zwischen dem ursprünglichen Pfad und Masse. So gibt es immer einen definierten Pegel und Probleme werden bestmöglich ausgeschlossen. <gallery> Datei:ZD-939L Elektronik vorne.JPG|Umgebaute Elektronik </gallery> Der erste Test im noch auseinander gebauten Zustand spricht für Erfolg: die Soll-Temperatur ist bei 160 °C, die Ist-Temperatur bleibt bei 25 °C. Nach Kippen des Schalters klettert die Anzeige wie vorher nach oben. <gallery> Datei:ZD-939L_Front_umgebaut.JPG|Funktionstest mit ausgeschalteter Heizung </gallery> =J-EXT= Auf dem Board befinden sich noch zwei Vorhalte für Stiftleisten. Eine unbeschriftete (vermutlich zum Download der Firmware) und eine namens J-EXT. Rein aus Neugierde habe ich mir letztere etwas genauer angesehen, vielleicht spricht das Board ja mit einem. Die Leiterbahnen führen schon einmal alle zum Mikrocontroller, zusammen mit dessen Datenblatt lassen sich die Pins zuordnen. P3.x haben leider keine spezielle Peripherie zugeordnet, also eher unwahrscheinlich, dass da UART rauskommt. Möglich ist aber alles. Also Spannung mit dem Scope nachgemessen und nach positivem Befund den Logic-Analyzer angeschlossen: [[Datei:ZD-939L_Logic-Analyzer.png]] Aus den Daten lässt sich folgende Zuordnung ableiten: {| class="wikitable" |- ! Pin J-EXT !! Pin µC !! Pin-Name !! Funktion |- | 1 || - || - || +5V |- | 2 || 7 || P3.1 || ? |- | 3 || 9 || P3.3 || Clock |- | 4 || 10 || P3.4 || Data |- | 5 || - || - || GND |} Ein "Datenpaket" dauert etwa 2,6 ms und wird alle 20 ms gesendet. Allem Anschein nach werden die Daten in 16-Bit-Gruppen geschickt, zumindest bleibt der Clock nach 16 Bits immer ein bisschen länger High. Die Daten habe ich nicht genauer untersucht, da für mich der Reiz einfach nicht da ist. Wer es versuchen will, kann sein Glück mit meiner Aufzeichnung versuchen: [[Datei:ZD-939L_J-EXT.zip]] Die Daten wurden mit Saleae Logic 1.1.18 Beta erstellt. Wenn ich mich richtig erinnere, war die Temperatur auf 160 °C Soll eingestellt und eine Ist-Temperatur von 25 °C (weniger macht das Teil anscheinend nicht) angezeigt. [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] 1bd2cbc4433b8298fb71e8716fc68afa56293e6c 890 889 2014-05-10T19:58:30Z Chris 2 links korrigiert wikitext text/x-wiki Vor geraumer Zeit hab ich mir eine Zhondi ZD-393L auf den Basteltisch gestellt. Diese ist gerade beim Entlöten von SMD-Bauteilen ein sehr nützlicher Helfer. [[Datei:ZD-939L Hinweis.JPG|thumb|Aufkleber als Workaround]] Eines hat mich allerdings vom ersten Tag weg gestört: sie hat keinen Nachlauf zum Kühlen des Heizelements. Als "Workaround" hat der Importeur lediglich einen Hinweis angebracht, dass man vor dem Abschalten auf die Mindesttemperatur herunterdrehen und eine Minute warten solle. Mit dem Warten kann ich leben, allerdings ist das Einstellen der Temperatur etwas nervig: Minus-Taster drücken und halten und sich für jedes Grad einen Pieps anhören. Nur um beim Nächsten Einschalten genau das Gegenteil zu machen. selbstverständlich ebenfalls mit akustischer Untermalung. Dabei gibt es die Heißluft-Station (neben der Version mit Nachlauf) auch mit dienen Schalter fürs Heizelement. Warum hat das meine nicht? Es wird höchste Zeit, dass sich das ändert. =Analyse= [[Datei:ZD-939L_Innenleben.jpg|thumb|Blick auf die hintere Leiterkarte]] Auf das Ding und reingeschaut. Die Elektronik ist auf 3 Leiterkarten verteilt - hinten befindet sich ein teilbestücktes Board auf das die Netzleitung führt. Nachdem sich nichts darauf befindet, das auf Regelung hindeutet, dürfte es der Leistungsteil sein. Vorne im Gehäuse findet sich neben der Leiterkarte mit den Tastern vom Frontpanel auch die Platine mit dem Display. Die 3 schwarzen Vielbeiner darauf lassen erahnen: hier wird höchstwahrscheinlich geregelt. Heizung abdrehen könnte man nun sowohl auf der Leistungs- als auch der mutmaßlichen Reglerplatine. Man könnte natürlich auch direkt in die Leitung zum Heizelement eingreifen - aber warum sich die Finger an 230 V verbrennen, wenn man es auch einfacher und sicher haben kann? Ein genauerer Blick auf die Display-Platine kann also nicht schaden: <gallery> Datei:ZD-939L Regler.JPG|Die Reglerplatine </gallery> Der 8-beinige Chip links ist ein LM358, also ein Operationsverstärker. Beim mittleren Chip im TQFP-Gehäuse handelt es sich um einen Silabs C8051F310 - einem Mikrocontroller. Rechts im Bild befindet sich ein Holtek HT1621B. Holtek kennt man auch als Mikrocontroller-Hersteller - aber zwei Mikrocontroller für einen einfachen Regler? Nicht ganz. Der Holtek ist lediglich ein LCD-Controller, was auch die Leiterbahnen zu ihm erklärt. Die Regelung übernimmt alleinig der Silabs-Chip. Interessanter als die Regelung und das Display ist für den Umbau, über welche Anschlüsse die Heizung angesteuert wird. Drei der vier Stiftleisten sind mit der Platine hinten verbunden. Die 4-polige Stiftleiste links im Bild führt zur Taster-Platine und fällt damit schon mal weg. Die untere zweipolige Stifleiste ist ein Kandidat - nachdem sie aber verdächtig nahe am LM358, ein paar diskreten Bauteilen und einem Poti liegt, dürfte es sich um den Anschluss für den Temperaturfühler sein. Alle Leitungen außer dieser verbunden bestätigt den Verdacht: Keine Temperaturanzeige. Bleiben nur noch zwei. Die links obere sieht verdächtig nach Stromversorgung aus: etwas dickere Leiterbahnen, Dioden und Kondensatoren. Nicht zuletzt ein 78L05. Warum aber 3 Pins? Eingangsspannung, Masse und Ausgangsspannung? Nein, vermutlich handelt es sich um eine symmetrische Versorgung - entweder fürs Display oder den Operationsverstärker. Ein Blick in den hinteren Teil der Lötstation bestätigt es: Ein Trafo mit Mittelabzapfung. Die Heizung muss also von der Stiftleiste rechts oben angesteuert werden. Am Stecker hängen zwei Drähte, was die Sache leichter macht. Masse lässt sich durchpiepsen und damit ist auch der Ausgang gefunden. Muss nur noch geklärt werden, wann welche Spannung anliegt und ob man einfach so einen Schalter einbringen kann. Multimeter angehängt und den Aparillo losbrummen lassen: 5V, wenn die Heizung an ist. Um sicherzustellen, dass die 5V berührungssicher sind, schnell gegen das Gehäuse, das mit PE verbunden ist: 0V, also galvanisch getrennt. Ausgezeichnet! =Umbau= Ein Ort für den zusätzlichen Schalter ist schnell gefunden: Neben dem Hauptschalter ist noch Platz. Der Akkuschrauber leiert ein Loch in die Platte und der Schalter ist drin. Für die elektrische Verbindung habe ich die Leitung zum "Backpanel" aufgetrennt und den Schalter einfach eingefügt. Da ich die Schaltung dahinter nicht genauer ansehen wollte, habe ich mich für die sicherere Ansteuerung entschlossen - theoretisch könnte man einfach eine der Leitungen auftrennen und den Schalter einfügen. Allerdings bekommt dann die Schaltung "hinten" entweder das Signal vom Mikrocontroller oder floatet durch die Gegend. Da das nicht besonders toll ist, wechselt der Schalter zwischen dem ursprünglichen Pfad und Masse. So gibt es immer einen definierten Pegel und Probleme werden bestmöglich ausgeschlossen. <gallery> Datei:ZD-939L Elektronik vorne.JPG|Umgebaute Elektronik </gallery> Der erste Test im noch auseinander gebauten Zustand spricht für Erfolg: die Soll-Temperatur ist bei 160 °C, die Ist-Temperatur bleibt bei 25 °C. Nach Kippen des Schalters klettert die Anzeige wie vorher nach oben. <gallery> Datei:ZD-939L Front umgebaut.JPG|Funktionstest mit ausgeschalteter Heizung </gallery> =J-EXT= Auf dem Board befinden sich noch zwei Vorhalte für Stiftleisten. Eine unbeschriftete (vermutlich zum Download der Firmware) und eine namens J-EXT. Rein aus Neugierde habe ich mir letztere etwas genauer angesehen, vielleicht spricht das Board ja mit einem. Die Leiterbahnen führen schon einmal alle zum Mikrocontroller, zusammen mit dessen Datenblatt lassen sich die Pins zuordnen. P3.x haben leider keine spezielle Peripherie zugeordnet, also eher unwahrscheinlich, dass da UART rauskommt. Möglich ist aber alles. Also Spannung mit dem Scope nachgemessen und nach positivem Befund den Logic-Analyzer angeschlossen: [[Datei:ZD-939L_Logic-Analyzer.png]] Aus den Daten lässt sich folgende Zuordnung ableiten: {| class="wikitable" |- ! Pin J-EXT !! Pin µC !! Pin-Name !! Funktion |- | 1 || - || - || +5V |- | 2 || 7 || P3.1 || ? |- | 3 || 9 || P3.3 || Clock |- | 4 || 10 || P3.4 || Data |- | 5 || - || - || GND |} Ein "Datenpaket" dauert etwa 2,6 ms und wird alle 20 ms gesendet. Allem Anschein nach werden die Daten in 16-Bit-Gruppen geschickt, zumindest bleibt der Clock nach 16 Bits immer ein bisschen länger High. Die Daten habe ich nicht genauer untersucht, da für mich der Reiz einfach nicht da ist. Wer es versuchen will, kann sein Glück mit meiner Aufzeichnung versuchen: [[Datei:ZD-939L J-EXT.zip]] Die Daten wurden mit Saleae Logic 1.1.18 Beta erstellt. Wenn ich mich richtig erinnere, war die Temperatur auf 160 °C Soll eingestellt und eine Ist-Temperatur von 25 °C (weniger macht das Teil anscheinend nicht) angezeigt. [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] dc2338c8f9c8493bcfd2275fbe0cdcab1a77a16b 892 890 2014-05-10T20:31:47Z Chris 2 Eine kleine Anmerkung zu chinesischen Namen wikitext text/x-wiki Vor geraumer Zeit hab ich mir eine Zhondi ZD-393L auf den Basteltisch gestellt. Diese ist gerade beim Entlöten von SMD-Bauteilen ein sehr nützlicher Helfer. [[Datei:ZD-939L Hinweis.JPG|thumb|Aufkleber als Workaround]] Eines hat mich allerdings vom ersten Tag weg gestört: sie hat keinen Nachlauf zum Kühlen des Heizelements. Als "Workaround" hat der Importeur lediglich einen Hinweis angebracht, dass man vor dem Abschalten auf die Mindesttemperatur herunterdrehen und eine Minute warten solle. Mit dem Warten kann ich leben, allerdings ist das Einstellen der Temperatur etwas nervig: Minus-Taster drücken und halten und sich für jedes Grad einen Pieps anhören. Nur um beim Nächsten Einschalten genau das Gegenteil zu machen. selbstverständlich ebenfalls mit akustischer Untermalung. Dabei gibt es die Heißluft-Station (neben der Version mit Nachlauf) auch mit dienen Schalter fürs Heizelement. Warum hat das meine nicht? Es wird höchste Zeit, dass sich das ändert. =Analyse= [[Datei:ZD-939L_Innenleben.jpg|thumb|Blick auf die hintere Leiterkarte]] Auf das Ding und reingeschaut. Die Elektronik ist auf 3 Leiterkarten verteilt - hinten befindet sich ein teilbestücktes Board auf das die Netzleitung führt. Nachdem sich nichts darauf befindet, das auf Regelung hindeutet, dürfte es der Leistungsteil sein. Vorne im Gehäuse findet sich neben der Leiterkarte mit den Tastern vom Frontpanel auch die Platine mit dem Display. Die 3 schwarzen Vielbeiner darauf lassen erahnen: hier wird höchstwahrscheinlich geregelt. Heizung abdrehen könnte man nun sowohl auf der Leistungs- als auch der mutmaßlichen Reglerplatine. Man könnte natürlich auch direkt in die Leitung zum Heizelement eingreifen - aber warum sich die Finger an 230 V verbrennen, wenn man es auch einfacher und sicher haben kann? Ein genauerer Blick auf die Display-Platine kann also nicht schaden: <gallery> Datei:ZD-939L Regler.JPG|Die Reglerplatine </gallery> Der 8-beinige Chip links ist ein LM358, also ein Operationsverstärker. Beim mittleren Chip im TQFP-Gehäuse handelt es sich um einen Silabs C8051F310 - einem Mikrocontroller. Rechts im Bild befindet sich ein Holtek HT1621B. Holtek kennt man auch als Mikrocontroller-Hersteller - aber zwei Mikrocontroller für einen einfachen Regler? Nicht ganz. Der Holtek ist lediglich ein LCD-Controller, was auch die Leiterbahnen zu ihm erklärt. Die Regelung übernimmt alleinig der Silabs-Chip. Interessanter als die Regelung und das Display ist für den Umbau, über welche Anschlüsse die Heizung angesteuert wird. Drei der vier Stiftleisten sind mit der Platine hinten verbunden. Die 4-polige Stiftleiste links im Bild führt zur Taster-Platine und fällt damit schon mal weg. Die untere zweipolige Stifleiste ist ein Kandidat - nachdem sie aber verdächtig nahe am LM358, ein paar diskreten Bauteilen und einem Poti liegt, dürfte es sich um den Anschluss für den Temperaturfühler sein. Alle Leitungen außer dieser verbunden bestätigt den Verdacht: Keine Temperaturanzeige. Bleiben nur noch zwei. Die links obere sieht verdächtig nach Stromversorgung aus: etwas dickere Leiterbahnen, Dioden und Kondensatoren. Nicht zuletzt ein 78L05. Warum aber 3 Pins? Eingangsspannung, Masse und Ausgangsspannung? Nein, vermutlich handelt es sich um eine symmetrische Versorgung - entweder fürs Display oder den Operationsverstärker. Ein Blick in den hinteren Teil der Lötstation bestätigt es: Ein Trafo mit Mittelabzapfung. Die Heizung muss also von der Stiftleiste rechts oben angesteuert werden. Am Stecker hängen zwei Drähte, was die Sache leichter macht. Masse lässt sich durchpiepsen und damit ist auch der Ausgang gefunden. Muss nur noch geklärt werden, wann welche Spannung anliegt und ob man einfach so einen Schalter einbringen kann. Multimeter angehängt und den Aparillo losbrummen lassen: 5V, wenn die Heizung an ist. Um sicherzustellen, dass die 5V berührungssicher sind, schnell gegen das Gehäuse, das mit PE verbunden ist: 0V, also galvanisch getrennt. Ausgezeichnet! =Umbau= Ein Ort für den zusätzlichen Schalter ist schnell gefunden: Neben dem Hauptschalter ist noch Platz. Der Akkuschrauber leiert ein Loch in die Platte und der Schalter ist drin. Für die elektrische Verbindung habe ich die Leitung zum "Backpanel" aufgetrennt und den Schalter einfach eingefügt. Da ich die Schaltung dahinter nicht genauer ansehen wollte, habe ich mich für die sicherere Ansteuerung entschlossen - theoretisch könnte man einfach eine der Leitungen auftrennen und den Schalter einfügen. Allerdings bekommt dann die Schaltung "hinten" entweder das Signal vom Mikrocontroller oder floatet durch die Gegend. Da das nicht besonders toll ist, wechselt der Schalter zwischen dem ursprünglichen Pfad und Masse. So gibt es immer einen definierten Pegel und Probleme werden bestmöglich ausgeschlossen. <gallery> Datei:ZD-939L Elektronik vorne.JPG|Umgebaute Elektronik </gallery> Der erste Test im noch auseinander gebauten Zustand spricht für Erfolg: die Soll-Temperatur ist bei 160 °C, die Ist-Temperatur bleibt bei 25 °C. Nach Kippen des Schalters klettert die Anzeige wie vorher nach oben. <gallery> Datei:ZD-939L Front umgebaut.JPG|Funktionstest mit ausgeschalteter Heizung </gallery> =J-EXT= Auf dem Board befinden sich noch zwei Vorhalte für Stiftleisten. Eine unbeschriftete (vermutlich zum Download der Firmware) und eine namens J-EXT. Rein aus Neugierde habe ich mir letztere etwas genauer angesehen, vielleicht spricht das Board ja mit einem. Die Leiterbahnen führen schon einmal alle zum Mikrocontroller, zusammen mit dessen Datenblatt lassen sich die Pins zuordnen. P3.x haben leider keine spezielle Peripherie zugeordnet, also eher unwahrscheinlich, dass da UART rauskommt. Möglich ist aber alles. Also Spannung mit dem Scope nachgemessen und nach positivem Befund den Logic-Analyzer angeschlossen: [[Datei:ZD-939L_Logic-Analyzer.png]] Aus den Daten lässt sich folgende Zuordnung ableiten: {| class="wikitable" |- ! Pin J-EXT !! Pin µC !! Pin-Name !! Funktion |- | 1 || - || - || +5V |- | 2 || 7 || P3.1 || ? |- | 3 || 9 || P3.3 || Clock |- | 4 || 10 || P3.4 || Data |- | 5 || - || - || GND |} Ein "Datenpaket" dauert etwa 2,6 ms und wird alle 20 ms gesendet. Allem Anschein nach werden die Daten in 16-Bit-Gruppen geschickt, zumindest bleibt der Clock nach 16 Bits immer ein bisschen länger High. Die Daten habe ich nicht genauer untersucht, da für mich der Reiz einfach nicht da ist. Wer es versuchen will, kann sein Glück mit meiner Aufzeichnung versuchen: [[Datei:ZD-939L J-EXT.zip]] Die Daten wurden mit Saleae Logic 1.1.18 Beta erstellt. Wenn ich mich richtig erinnere, war die Temperatur auf 160 °C Soll eingestellt und eine Ist-Temperatur von 25 °C (weniger macht das Teil anscheinend nicht) angezeigt. =Siehe auch= * [http://hobbyelektronik.org/b/2014/05/eine-kleine-anmerkung-zu-chinesischen-namen/ Eine kleine Anmerkung zu chinesischen Namen] [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] 14a7c8c7a6a267a8c623278b3d23f582d493cfa3 893 892 2014-05-10T20:32:31Z Chris 2 Kleinkram wikitext text/x-wiki Vor geraumer Zeit hab ich mir eine Zhondi ZD-393L auf den Basteltisch gestellt. Diese Heißluftlötstation ist gerade beim Entlöten von SMD-Bauteilen ein sehr nützlicher Helfer. [[Datei:ZD-939L Hinweis.JPG|thumb|Aufkleber als Workaround]] Eines hat mich allerdings vom ersten Tag weg gestört: sie hat keinen Nachlauf zum Kühlen des Heizelements. Als "Workaround" hat der Importeur lediglich einen Hinweis angebracht, dass man vor dem Abschalten auf die Mindesttemperatur herunterdrehen und eine Minute warten solle. Mit dem Warten kann ich leben, allerdings ist das Einstellen der Temperatur etwas nervig: Minus-Taster drücken und halten und sich für jedes Grad einen Pieps anhören. Nur um beim Nächsten Einschalten genau das Gegenteil zu machen. selbstverständlich ebenfalls mit akustischer Untermalung. Dabei gibt es die Heißluft-Station (neben der Version mit Nachlauf) auch mit dienen Schalter fürs Heizelement. Warum hat das meine nicht? Es wird höchste Zeit, dass sich das ändert. =Analyse= [[Datei:ZD-939L_Innenleben.jpg|thumb|Blick auf die hintere Leiterkarte]] Auf das Ding und reingeschaut. Die Elektronik ist auf 3 Leiterkarten verteilt - hinten befindet sich ein teilbestücktes Board auf das die Netzleitung führt. Nachdem sich nichts darauf befindet, das auf Regelung hindeutet, dürfte es der Leistungsteil sein. Vorne im Gehäuse findet sich neben der Leiterkarte mit den Tastern vom Frontpanel auch die Platine mit dem Display. Die 3 schwarzen Vielbeiner darauf lassen erahnen: hier wird höchstwahrscheinlich geregelt. Heizung abdrehen könnte man nun sowohl auf der Leistungs- als auch der mutmaßlichen Reglerplatine. Man könnte natürlich auch direkt in die Leitung zum Heizelement eingreifen - aber warum sich die Finger an 230 V verbrennen, wenn man es auch einfacher und sicher haben kann? Ein genauerer Blick auf die Display-Platine kann also nicht schaden: <gallery> Datei:ZD-939L Regler.JPG|Die Reglerplatine </gallery> Der 8-beinige Chip links ist ein LM358, also ein Operationsverstärker. Beim mittleren Chip im TQFP-Gehäuse handelt es sich um einen Silabs C8051F310 - einem Mikrocontroller. Rechts im Bild befindet sich ein Holtek HT1621B. Holtek kennt man auch als Mikrocontroller-Hersteller - aber zwei Mikrocontroller für einen einfachen Regler? Nicht ganz. Der Holtek ist lediglich ein LCD-Controller, was auch die Leiterbahnen zu ihm erklärt. Die Regelung übernimmt alleinig der Silabs-Chip. Interessanter als die Regelung und das Display ist für den Umbau, über welche Anschlüsse die Heizung angesteuert wird. Drei der vier Stiftleisten sind mit der Platine hinten verbunden. Die 4-polige Stiftleiste links im Bild führt zur Taster-Platine und fällt damit schon mal weg. Die untere zweipolige Stifleiste ist ein Kandidat - nachdem sie aber verdächtig nahe am LM358, ein paar diskreten Bauteilen und einem Poti liegt, dürfte es sich um den Anschluss für den Temperaturfühler sein. Alle Leitungen außer dieser verbunden bestätigt den Verdacht: Keine Temperaturanzeige. Bleiben nur noch zwei. Die links obere sieht verdächtig nach Stromversorgung aus: etwas dickere Leiterbahnen, Dioden und Kondensatoren. Nicht zuletzt ein 78L05. Warum aber 3 Pins? Eingangsspannung, Masse und Ausgangsspannung? Nein, vermutlich handelt es sich um eine symmetrische Versorgung - entweder fürs Display oder den Operationsverstärker. Ein Blick in den hinteren Teil der Lötstation bestätigt es: Ein Trafo mit Mittelabzapfung. Die Heizung muss also von der Stiftleiste rechts oben angesteuert werden. Am Stecker hängen zwei Drähte, was die Sache leichter macht. Masse lässt sich durchpiepsen und damit ist auch der Ausgang gefunden. Muss nur noch geklärt werden, wann welche Spannung anliegt und ob man einfach so einen Schalter einbringen kann. Multimeter angehängt und den Aparillo losbrummen lassen: 5V, wenn die Heizung an ist. Um sicherzustellen, dass die 5V berührungssicher sind, schnell gegen das Gehäuse, das mit PE verbunden ist: 0V, also galvanisch getrennt. Ausgezeichnet! =Umbau= Ein Ort für den zusätzlichen Schalter ist schnell gefunden: Neben dem Hauptschalter ist noch Platz. Der Akkuschrauber leiert ein Loch in die Platte und der Schalter ist drin. Für die elektrische Verbindung habe ich die Leitung zum "Backpanel" aufgetrennt und den Schalter einfach eingefügt. Da ich die Schaltung dahinter nicht genauer ansehen wollte, habe ich mich für die sicherere Ansteuerung entschlossen - theoretisch könnte man einfach eine der Leitungen auftrennen und den Schalter einfügen. Allerdings bekommt dann die Schaltung "hinten" entweder das Signal vom Mikrocontroller oder floatet durch die Gegend. Da das nicht besonders toll ist, wechselt der Schalter zwischen dem ursprünglichen Pfad und Masse. So gibt es immer einen definierten Pegel und Probleme werden bestmöglich ausgeschlossen. <gallery> Datei:ZD-939L Elektronik vorne.JPG|Umgebaute Elektronik </gallery> Der erste Test im noch auseinander gebauten Zustand spricht für Erfolg: die Soll-Temperatur ist bei 160 °C, die Ist-Temperatur bleibt bei 25 °C. Nach Kippen des Schalters klettert die Anzeige wie vorher nach oben. <gallery> Datei:ZD-939L Front umgebaut.JPG|Funktionstest mit ausgeschalteter Heizung </gallery> =J-EXT= Auf dem Board befinden sich noch zwei Vorhalte für Stiftleisten. Eine unbeschriftete (vermutlich zum Download der Firmware) und eine namens J-EXT. Rein aus Neugierde habe ich mir letztere etwas genauer angesehen, vielleicht spricht das Board ja mit einem. Die Leiterbahnen führen schon einmal alle zum Mikrocontroller, zusammen mit dessen Datenblatt lassen sich die Pins zuordnen. P3.x haben leider keine spezielle Peripherie zugeordnet, also eher unwahrscheinlich, dass da UART rauskommt. Möglich ist aber alles. Also Spannung mit dem Scope nachgemessen und nach positivem Befund den Logic-Analyzer angeschlossen: [[Datei:ZD-939L_Logic-Analyzer.png]] Aus den Daten lässt sich folgende Zuordnung ableiten: {| class="wikitable" |- ! Pin J-EXT !! Pin µC !! Pin-Name !! Funktion |- | 1 || - || - || +5V |- | 2 || 7 || P3.1 || ? |- | 3 || 9 || P3.3 || Clock |- | 4 || 10 || P3.4 || Data |- | 5 || - || - || GND |} Ein "Datenpaket" dauert etwa 2,6 ms und wird alle 20 ms gesendet. Allem Anschein nach werden die Daten in 16-Bit-Gruppen geschickt, zumindest bleibt der Clock nach 16 Bits immer ein bisschen länger High. Die Daten habe ich nicht genauer untersucht, da für mich der Reiz einfach nicht da ist. Wer es versuchen will, kann sein Glück mit meiner Aufzeichnung versuchen: [[Datei:ZD-939L J-EXT.zip]] Die Daten wurden mit Saleae Logic 1.1.18 Beta erstellt. Wenn ich mich richtig erinnere, war die Temperatur auf 160 °C Soll eingestellt und eine Ist-Temperatur von 25 °C (weniger macht das Teil anscheinend nicht) angezeigt. =Siehe auch= * [http://hobbyelektronik.org/b/2014/05/eine-kleine-anmerkung-zu-chinesischen-namen/ Eine kleine Anmerkung zu chinesischen Namen] [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] 772f98356f0fc0e12a274315a88b51558923c63f 905 893 2014-06-24T19:05:30Z Qsysopr 1 verschob „[[Kühlung für Zhongdi ZD-393L]]“ nach „[[Kühlung für Zhongdi ZD-933L]]“: Zahlendreher wikitext text/x-wiki Vor geraumer Zeit hab ich mir eine Zhondi ZD-393L auf den Basteltisch gestellt. Diese Heißluftlötstation ist gerade beim Entlöten von SMD-Bauteilen ein sehr nützlicher Helfer. [[Datei:ZD-939L Hinweis.JPG|thumb|Aufkleber als Workaround]] Eines hat mich allerdings vom ersten Tag weg gestört: sie hat keinen Nachlauf zum Kühlen des Heizelements. Als "Workaround" hat der Importeur lediglich einen Hinweis angebracht, dass man vor dem Abschalten auf die Mindesttemperatur herunterdrehen und eine Minute warten solle. Mit dem Warten kann ich leben, allerdings ist das Einstellen der Temperatur etwas nervig: Minus-Taster drücken und halten und sich für jedes Grad einen Pieps anhören. Nur um beim Nächsten Einschalten genau das Gegenteil zu machen. selbstverständlich ebenfalls mit akustischer Untermalung. Dabei gibt es die Heißluft-Station (neben der Version mit Nachlauf) auch mit dienen Schalter fürs Heizelement. Warum hat das meine nicht? Es wird höchste Zeit, dass sich das ändert. =Analyse= [[Datei:ZD-939L_Innenleben.jpg|thumb|Blick auf die hintere Leiterkarte]] Auf das Ding und reingeschaut. Die Elektronik ist auf 3 Leiterkarten verteilt - hinten befindet sich ein teilbestücktes Board auf das die Netzleitung führt. Nachdem sich nichts darauf befindet, das auf Regelung hindeutet, dürfte es der Leistungsteil sein. Vorne im Gehäuse findet sich neben der Leiterkarte mit den Tastern vom Frontpanel auch die Platine mit dem Display. Die 3 schwarzen Vielbeiner darauf lassen erahnen: hier wird höchstwahrscheinlich geregelt. Heizung abdrehen könnte man nun sowohl auf der Leistungs- als auch der mutmaßlichen Reglerplatine. Man könnte natürlich auch direkt in die Leitung zum Heizelement eingreifen - aber warum sich die Finger an 230 V verbrennen, wenn man es auch einfacher und sicher haben kann? Ein genauerer Blick auf die Display-Platine kann also nicht schaden: <gallery> Datei:ZD-939L Regler.JPG|Die Reglerplatine </gallery> Der 8-beinige Chip links ist ein LM358, also ein Operationsverstärker. Beim mittleren Chip im TQFP-Gehäuse handelt es sich um einen Silabs C8051F310 - einem Mikrocontroller. Rechts im Bild befindet sich ein Holtek HT1621B. Holtek kennt man auch als Mikrocontroller-Hersteller - aber zwei Mikrocontroller für einen einfachen Regler? Nicht ganz. Der Holtek ist lediglich ein LCD-Controller, was auch die Leiterbahnen zu ihm erklärt. Die Regelung übernimmt alleinig der Silabs-Chip. Interessanter als die Regelung und das Display ist für den Umbau, über welche Anschlüsse die Heizung angesteuert wird. Drei der vier Stiftleisten sind mit der Platine hinten verbunden. Die 4-polige Stiftleiste links im Bild führt zur Taster-Platine und fällt damit schon mal weg. Die untere zweipolige Stifleiste ist ein Kandidat - nachdem sie aber verdächtig nahe am LM358, ein paar diskreten Bauteilen und einem Poti liegt, dürfte es sich um den Anschluss für den Temperaturfühler sein. Alle Leitungen außer dieser verbunden bestätigt den Verdacht: Keine Temperaturanzeige. Bleiben nur noch zwei. Die links obere sieht verdächtig nach Stromversorgung aus: etwas dickere Leiterbahnen, Dioden und Kondensatoren. Nicht zuletzt ein 78L05. Warum aber 3 Pins? Eingangsspannung, Masse und Ausgangsspannung? Nein, vermutlich handelt es sich um eine symmetrische Versorgung - entweder fürs Display oder den Operationsverstärker. Ein Blick in den hinteren Teil der Lötstation bestätigt es: Ein Trafo mit Mittelabzapfung. Die Heizung muss also von der Stiftleiste rechts oben angesteuert werden. Am Stecker hängen zwei Drähte, was die Sache leichter macht. Masse lässt sich durchpiepsen und damit ist auch der Ausgang gefunden. Muss nur noch geklärt werden, wann welche Spannung anliegt und ob man einfach so einen Schalter einbringen kann. Multimeter angehängt und den Aparillo losbrummen lassen: 5V, wenn die Heizung an ist. Um sicherzustellen, dass die 5V berührungssicher sind, schnell gegen das Gehäuse, das mit PE verbunden ist: 0V, also galvanisch getrennt. Ausgezeichnet! =Umbau= Ein Ort für den zusätzlichen Schalter ist schnell gefunden: Neben dem Hauptschalter ist noch Platz. Der Akkuschrauber leiert ein Loch in die Platte und der Schalter ist drin. Für die elektrische Verbindung habe ich die Leitung zum "Backpanel" aufgetrennt und den Schalter einfach eingefügt. Da ich die Schaltung dahinter nicht genauer ansehen wollte, habe ich mich für die sicherere Ansteuerung entschlossen - theoretisch könnte man einfach eine der Leitungen auftrennen und den Schalter einfügen. Allerdings bekommt dann die Schaltung "hinten" entweder das Signal vom Mikrocontroller oder floatet durch die Gegend. Da das nicht besonders toll ist, wechselt der Schalter zwischen dem ursprünglichen Pfad und Masse. So gibt es immer einen definierten Pegel und Probleme werden bestmöglich ausgeschlossen. <gallery> Datei:ZD-939L Elektronik vorne.JPG|Umgebaute Elektronik </gallery> Der erste Test im noch auseinander gebauten Zustand spricht für Erfolg: die Soll-Temperatur ist bei 160 °C, die Ist-Temperatur bleibt bei 25 °C. Nach Kippen des Schalters klettert die Anzeige wie vorher nach oben. <gallery> Datei:ZD-939L Front umgebaut.JPG|Funktionstest mit ausgeschalteter Heizung </gallery> =J-EXT= Auf dem Board befinden sich noch zwei Vorhalte für Stiftleisten. Eine unbeschriftete (vermutlich zum Download der Firmware) und eine namens J-EXT. Rein aus Neugierde habe ich mir letztere etwas genauer angesehen, vielleicht spricht das Board ja mit einem. Die Leiterbahnen führen schon einmal alle zum Mikrocontroller, zusammen mit dessen Datenblatt lassen sich die Pins zuordnen. P3.x haben leider keine spezielle Peripherie zugeordnet, also eher unwahrscheinlich, dass da UART rauskommt. Möglich ist aber alles. Also Spannung mit dem Scope nachgemessen und nach positivem Befund den Logic-Analyzer angeschlossen: [[Datei:ZD-939L_Logic-Analyzer.png]] Aus den Daten lässt sich folgende Zuordnung ableiten: {| class="wikitable" |- ! Pin J-EXT !! Pin µC !! Pin-Name !! Funktion |- | 1 || - || - || +5V |- | 2 || 7 || P3.1 || ? |- | 3 || 9 || P3.3 || Clock |- | 4 || 10 || P3.4 || Data |- | 5 || - || - || GND |} Ein "Datenpaket" dauert etwa 2,6 ms und wird alle 20 ms gesendet. Allem Anschein nach werden die Daten in 16-Bit-Gruppen geschickt, zumindest bleibt der Clock nach 16 Bits immer ein bisschen länger High. Die Daten habe ich nicht genauer untersucht, da für mich der Reiz einfach nicht da ist. Wer es versuchen will, kann sein Glück mit meiner Aufzeichnung versuchen: [[Datei:ZD-939L J-EXT.zip]] Die Daten wurden mit Saleae Logic 1.1.18 Beta erstellt. Wenn ich mich richtig erinnere, war die Temperatur auf 160 °C Soll eingestellt und eine Ist-Temperatur von 25 °C (weniger macht das Teil anscheinend nicht) angezeigt. =Siehe auch= * [http://hobbyelektronik.org/b/2014/05/eine-kleine-anmerkung-zu-chinesischen-namen/ Eine kleine Anmerkung zu chinesischen Namen] [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] 772f98356f0fc0e12a274315a88b51558923c63f 907 905 2014-06-24T19:05:54Z Qsysopr 1 verschob „[[Kühlung für Zhongdi ZD-933L]]“ nach „[[Kühlung für Zhongdi ZD-939L]]“ wikitext text/x-wiki Vor geraumer Zeit hab ich mir eine Zhondi ZD-393L auf den Basteltisch gestellt. Diese Heißluftlötstation ist gerade beim Entlöten von SMD-Bauteilen ein sehr nützlicher Helfer. [[Datei:ZD-939L Hinweis.JPG|thumb|Aufkleber als Workaround]] Eines hat mich allerdings vom ersten Tag weg gestört: sie hat keinen Nachlauf zum Kühlen des Heizelements. Als "Workaround" hat der Importeur lediglich einen Hinweis angebracht, dass man vor dem Abschalten auf die Mindesttemperatur herunterdrehen und eine Minute warten solle. Mit dem Warten kann ich leben, allerdings ist das Einstellen der Temperatur etwas nervig: Minus-Taster drücken und halten und sich für jedes Grad einen Pieps anhören. Nur um beim Nächsten Einschalten genau das Gegenteil zu machen. selbstverständlich ebenfalls mit akustischer Untermalung. Dabei gibt es die Heißluft-Station (neben der Version mit Nachlauf) auch mit dienen Schalter fürs Heizelement. Warum hat das meine nicht? Es wird höchste Zeit, dass sich das ändert. =Analyse= [[Datei:ZD-939L_Innenleben.jpg|thumb|Blick auf die hintere Leiterkarte]] Auf das Ding und reingeschaut. Die Elektronik ist auf 3 Leiterkarten verteilt - hinten befindet sich ein teilbestücktes Board auf das die Netzleitung führt. Nachdem sich nichts darauf befindet, das auf Regelung hindeutet, dürfte es der Leistungsteil sein. Vorne im Gehäuse findet sich neben der Leiterkarte mit den Tastern vom Frontpanel auch die Platine mit dem Display. Die 3 schwarzen Vielbeiner darauf lassen erahnen: hier wird höchstwahrscheinlich geregelt. Heizung abdrehen könnte man nun sowohl auf der Leistungs- als auch der mutmaßlichen Reglerplatine. Man könnte natürlich auch direkt in die Leitung zum Heizelement eingreifen - aber warum sich die Finger an 230 V verbrennen, wenn man es auch einfacher und sicher haben kann? Ein genauerer Blick auf die Display-Platine kann also nicht schaden: <gallery> Datei:ZD-939L Regler.JPG|Die Reglerplatine </gallery> Der 8-beinige Chip links ist ein LM358, also ein Operationsverstärker. Beim mittleren Chip im TQFP-Gehäuse handelt es sich um einen Silabs C8051F310 - einem Mikrocontroller. Rechts im Bild befindet sich ein Holtek HT1621B. Holtek kennt man auch als Mikrocontroller-Hersteller - aber zwei Mikrocontroller für einen einfachen Regler? Nicht ganz. Der Holtek ist lediglich ein LCD-Controller, was auch die Leiterbahnen zu ihm erklärt. Die Regelung übernimmt alleinig der Silabs-Chip. Interessanter als die Regelung und das Display ist für den Umbau, über welche Anschlüsse die Heizung angesteuert wird. Drei der vier Stiftleisten sind mit der Platine hinten verbunden. Die 4-polige Stiftleiste links im Bild führt zur Taster-Platine und fällt damit schon mal weg. Die untere zweipolige Stifleiste ist ein Kandidat - nachdem sie aber verdächtig nahe am LM358, ein paar diskreten Bauteilen und einem Poti liegt, dürfte es sich um den Anschluss für den Temperaturfühler sein. Alle Leitungen außer dieser verbunden bestätigt den Verdacht: Keine Temperaturanzeige. Bleiben nur noch zwei. Die links obere sieht verdächtig nach Stromversorgung aus: etwas dickere Leiterbahnen, Dioden und Kondensatoren. Nicht zuletzt ein 78L05. Warum aber 3 Pins? Eingangsspannung, Masse und Ausgangsspannung? Nein, vermutlich handelt es sich um eine symmetrische Versorgung - entweder fürs Display oder den Operationsverstärker. Ein Blick in den hinteren Teil der Lötstation bestätigt es: Ein Trafo mit Mittelabzapfung. Die Heizung muss also von der Stiftleiste rechts oben angesteuert werden. Am Stecker hängen zwei Drähte, was die Sache leichter macht. Masse lässt sich durchpiepsen und damit ist auch der Ausgang gefunden. Muss nur noch geklärt werden, wann welche Spannung anliegt und ob man einfach so einen Schalter einbringen kann. Multimeter angehängt und den Aparillo losbrummen lassen: 5V, wenn die Heizung an ist. Um sicherzustellen, dass die 5V berührungssicher sind, schnell gegen das Gehäuse, das mit PE verbunden ist: 0V, also galvanisch getrennt. Ausgezeichnet! =Umbau= Ein Ort für den zusätzlichen Schalter ist schnell gefunden: Neben dem Hauptschalter ist noch Platz. Der Akkuschrauber leiert ein Loch in die Platte und der Schalter ist drin. Für die elektrische Verbindung habe ich die Leitung zum "Backpanel" aufgetrennt und den Schalter einfach eingefügt. Da ich die Schaltung dahinter nicht genauer ansehen wollte, habe ich mich für die sicherere Ansteuerung entschlossen - theoretisch könnte man einfach eine der Leitungen auftrennen und den Schalter einfügen. Allerdings bekommt dann die Schaltung "hinten" entweder das Signal vom Mikrocontroller oder floatet durch die Gegend. Da das nicht besonders toll ist, wechselt der Schalter zwischen dem ursprünglichen Pfad und Masse. So gibt es immer einen definierten Pegel und Probleme werden bestmöglich ausgeschlossen. <gallery> Datei:ZD-939L Elektronik vorne.JPG|Umgebaute Elektronik </gallery> Der erste Test im noch auseinander gebauten Zustand spricht für Erfolg: die Soll-Temperatur ist bei 160 °C, die Ist-Temperatur bleibt bei 25 °C. Nach Kippen des Schalters klettert die Anzeige wie vorher nach oben. <gallery> Datei:ZD-939L Front umgebaut.JPG|Funktionstest mit ausgeschalteter Heizung </gallery> =J-EXT= Auf dem Board befinden sich noch zwei Vorhalte für Stiftleisten. Eine unbeschriftete (vermutlich zum Download der Firmware) und eine namens J-EXT. Rein aus Neugierde habe ich mir letztere etwas genauer angesehen, vielleicht spricht das Board ja mit einem. Die Leiterbahnen führen schon einmal alle zum Mikrocontroller, zusammen mit dessen Datenblatt lassen sich die Pins zuordnen. P3.x haben leider keine spezielle Peripherie zugeordnet, also eher unwahrscheinlich, dass da UART rauskommt. Möglich ist aber alles. Also Spannung mit dem Scope nachgemessen und nach positivem Befund den Logic-Analyzer angeschlossen: [[Datei:ZD-939L_Logic-Analyzer.png]] Aus den Daten lässt sich folgende Zuordnung ableiten: {| class="wikitable" |- ! Pin J-EXT !! Pin µC !! Pin-Name !! Funktion |- | 1 || - || - || +5V |- | 2 || 7 || P3.1 || ? |- | 3 || 9 || P3.3 || Clock |- | 4 || 10 || P3.4 || Data |- | 5 || - || - || GND |} Ein "Datenpaket" dauert etwa 2,6 ms und wird alle 20 ms gesendet. Allem Anschein nach werden die Daten in 16-Bit-Gruppen geschickt, zumindest bleibt der Clock nach 16 Bits immer ein bisschen länger High. Die Daten habe ich nicht genauer untersucht, da für mich der Reiz einfach nicht da ist. Wer es versuchen will, kann sein Glück mit meiner Aufzeichnung versuchen: [[Datei:ZD-939L J-EXT.zip]] Die Daten wurden mit Saleae Logic 1.1.18 Beta erstellt. Wenn ich mich richtig erinnere, war die Temperatur auf 160 °C Soll eingestellt und eine Ist-Temperatur von 25 °C (weniger macht das Teil anscheinend nicht) angezeigt. =Siehe auch= * [http://hobbyelektronik.org/b/2014/05/eine-kleine-anmerkung-zu-chinesischen-namen/ Eine kleine Anmerkung zu chinesischen Namen] [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] 772f98356f0fc0e12a274315a88b51558923c63f 910 907 2014-06-24T19:07:08Z Qsysopr 1 Zahlendreher korrigiert, vielen Dank an Manfred! wikitext text/x-wiki Vor geraumer Zeit hab ich mir eine Zhondi ZD-939L auf den Basteltisch gestellt. Diese Heißluftlötstation ist gerade beim Entlöten von SMD-Bauteilen ein sehr nützlicher Helfer. [[Datei:ZD-939L Hinweis.JPG|thumb|Aufkleber als Workaround]] Eines hat mich allerdings vom ersten Tag weg gestört: sie hat keinen Nachlauf zum Kühlen des Heizelements. Als "Workaround" hat der Importeur lediglich einen Hinweis angebracht, dass man vor dem Abschalten auf die Mindesttemperatur herunterdrehen und eine Minute warten solle. Mit dem Warten kann ich leben, allerdings ist das Einstellen der Temperatur etwas nervig: Minus-Taster drücken und halten und sich für jedes Grad einen Pieps anhören. Nur um beim Nächsten Einschalten genau das Gegenteil zu machen. selbstverständlich ebenfalls mit akustischer Untermalung. Dabei gibt es die Heißluft-Station (neben der Version mit Nachlauf) auch mit dienen Schalter fürs Heizelement. Warum hat das meine nicht? Es wird höchste Zeit, dass sich das ändert. =Analyse= [[Datei:ZD-939L_Innenleben.jpg|thumb|Blick auf die hintere Leiterkarte]] Auf das Ding und reingeschaut. Die Elektronik ist auf 3 Leiterkarten verteilt - hinten befindet sich ein teilbestücktes Board auf das die Netzleitung führt. Nachdem sich nichts darauf befindet, das auf Regelung hindeutet, dürfte es der Leistungsteil sein. Vorne im Gehäuse findet sich neben der Leiterkarte mit den Tastern vom Frontpanel auch die Platine mit dem Display. Die 3 schwarzen Vielbeiner darauf lassen erahnen: hier wird höchstwahrscheinlich geregelt. Heizung abdrehen könnte man nun sowohl auf der Leistungs- als auch der mutmaßlichen Reglerplatine. Man könnte natürlich auch direkt in die Leitung zum Heizelement eingreifen - aber warum sich die Finger an 230 V verbrennen, wenn man es auch einfacher und sicher haben kann? Ein genauerer Blick auf die Display-Platine kann also nicht schaden: <gallery> Datei:ZD-939L Regler.JPG|Die Reglerplatine </gallery> Der 8-beinige Chip links ist ein LM358, also ein Operationsverstärker. Beim mittleren Chip im TQFP-Gehäuse handelt es sich um einen Silabs C8051F310 - einem Mikrocontroller. Rechts im Bild befindet sich ein Holtek HT1621B. Holtek kennt man auch als Mikrocontroller-Hersteller - aber zwei Mikrocontroller für einen einfachen Regler? Nicht ganz. Der Holtek ist lediglich ein LCD-Controller, was auch die Leiterbahnen zu ihm erklärt. Die Regelung übernimmt alleinig der Silabs-Chip. Interessanter als die Regelung und das Display ist für den Umbau, über welche Anschlüsse die Heizung angesteuert wird. Drei der vier Stiftleisten sind mit der Platine hinten verbunden. Die 4-polige Stiftleiste links im Bild führt zur Taster-Platine und fällt damit schon mal weg. Die untere zweipolige Stifleiste ist ein Kandidat - nachdem sie aber verdächtig nahe am LM358, ein paar diskreten Bauteilen und einem Poti liegt, dürfte es sich um den Anschluss für den Temperaturfühler sein. Alle Leitungen außer dieser verbunden bestätigt den Verdacht: Keine Temperaturanzeige. Bleiben nur noch zwei. Die links obere sieht verdächtig nach Stromversorgung aus: etwas dickere Leiterbahnen, Dioden und Kondensatoren. Nicht zuletzt ein 78L05. Warum aber 3 Pins? Eingangsspannung, Masse und Ausgangsspannung? Nein, vermutlich handelt es sich um eine symmetrische Versorgung - entweder fürs Display oder den Operationsverstärker. Ein Blick in den hinteren Teil der Lötstation bestätigt es: Ein Trafo mit Mittelabzapfung. Die Heizung muss also von der Stiftleiste rechts oben angesteuert werden. Am Stecker hängen zwei Drähte, was die Sache leichter macht. Masse lässt sich durchpiepsen und damit ist auch der Ausgang gefunden. Muss nur noch geklärt werden, wann welche Spannung anliegt und ob man einfach so einen Schalter einbringen kann. Multimeter angehängt und den Aparillo losbrummen lassen: 5V, wenn die Heizung an ist. Um sicherzustellen, dass die 5V berührungssicher sind, schnell gegen das Gehäuse, das mit PE verbunden ist: 0V, also galvanisch getrennt. Ausgezeichnet! =Umbau= Ein Ort für den zusätzlichen Schalter ist schnell gefunden: Neben dem Hauptschalter ist noch Platz. Der Akkuschrauber leiert ein Loch in die Platte und der Schalter ist drin. Für die elektrische Verbindung habe ich die Leitung zum "Backpanel" aufgetrennt und den Schalter einfach eingefügt. Da ich die Schaltung dahinter nicht genauer ansehen wollte, habe ich mich für die sicherere Ansteuerung entschlossen - theoretisch könnte man einfach eine der Leitungen auftrennen und den Schalter einfügen. Allerdings bekommt dann die Schaltung "hinten" entweder das Signal vom Mikrocontroller oder floatet durch die Gegend. Da das nicht besonders toll ist, wechselt der Schalter zwischen dem ursprünglichen Pfad und Masse. So gibt es immer einen definierten Pegel und Probleme werden bestmöglich ausgeschlossen. <gallery> Datei:ZD-939L Elektronik vorne.JPG|Umgebaute Elektronik </gallery> Der erste Test im noch auseinander gebauten Zustand spricht für Erfolg: die Soll-Temperatur ist bei 160 °C, die Ist-Temperatur bleibt bei 25 °C. Nach Kippen des Schalters klettert die Anzeige wie vorher nach oben. <gallery> Datei:ZD-939L Front umgebaut.JPG|Funktionstest mit ausgeschalteter Heizung </gallery> =J-EXT= Auf dem Board befinden sich noch zwei Vorhalte für Stiftleisten. Eine unbeschriftete (vermutlich zum Download der Firmware) und eine namens J-EXT. Rein aus Neugierde habe ich mir letztere etwas genauer angesehen, vielleicht spricht das Board ja mit einem. Die Leiterbahnen führen schon einmal alle zum Mikrocontroller, zusammen mit dessen Datenblatt lassen sich die Pins zuordnen. P3.x haben leider keine spezielle Peripherie zugeordnet, also eher unwahrscheinlich, dass da UART rauskommt. Möglich ist aber alles. Also Spannung mit dem Scope nachgemessen und nach positivem Befund den Logic-Analyzer angeschlossen: [[Datei:ZD-939L_Logic-Analyzer.png]] Aus den Daten lässt sich folgende Zuordnung ableiten: {| class="wikitable" |- ! Pin J-EXT !! Pin µC !! Pin-Name !! Funktion |- | 1 || - || - || +5V |- | 2 || 7 || P3.1 || ? |- | 3 || 9 || P3.3 || Clock |- | 4 || 10 || P3.4 || Data |- | 5 || - || - || GND |} Ein "Datenpaket" dauert etwa 2,6 ms und wird alle 20 ms gesendet. Allem Anschein nach werden die Daten in 16-Bit-Gruppen geschickt, zumindest bleibt der Clock nach 16 Bits immer ein bisschen länger High. Die Daten habe ich nicht genauer untersucht, da für mich der Reiz einfach nicht da ist. Wer es versuchen will, kann sein Glück mit meiner Aufzeichnung versuchen: [[Datei:ZD-939L J-EXT.zip]] Die Daten wurden mit Saleae Logic 1.1.18 Beta erstellt. Wenn ich mich richtig erinnere, war die Temperatur auf 160 °C Soll eingestellt und eine Ist-Temperatur von 25 °C (weniger macht das Teil anscheinend nicht) angezeigt. =Siehe auch= * [http://hobbyelektronik.org/b/2014/05/eine-kleine-anmerkung-zu-chinesischen-namen/ Eine kleine Anmerkung zu chinesischen Namen] [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] b7d34f9245ea4fad0e0f93061010f11cc2a51444 Hauptseite 0 1 891 880 2014-05-10T19:59:50Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *10.05.2014 [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 [[EAGLE-Bibliotheken]] *10.11.2013 [[Zeitraffer mit Linux]] *14.08.2013 [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 [[Farnell-Assistent]] *16.01.2013 [[Halbleiterelektronik-Formelsammlung]] ==Änderungen== *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio 6179be6f42b09eafb1f12404ff64ed5bf941cb9f 911 891 2014-06-24T19:10:18Z Qsysopr 1 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] *02.02.2014 [[EAGLE-Bibliotheken]] *10.11.2013 [[Zeitraffer mit Linux]] *14.08.2013 [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 [[Farnell-Assistent]] *16.01.2013 [[Halbleiterelektronik-Formelsammlung]] ==Änderungen== *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio 425059ec19d4e37a7e7d416502966708f03388b9 EAGLE-Bibliotheken 0 358 894 878 2014-05-21T04:18:47Z Chris 2 Dateilink korrigiert (Danke, Randolf!) wikitext text/x-wiki Über die Zeit sind bei mir einige Bibliotheken für EAGLE entstanden. Damit sie nicht nur auf meiner Festplatte ihr Dasein fristen und dem ein oder anderen die Arbeit erleichtern, hier zukünftig tendenziell wachsende Auswahl meiner Libs: = Konnektoren = == Simplecon == Mit dieser Bibliothek können Stiftleisten an der Kante platziert werden. Die Pads sind versetzt angeordnet, sodass sich sowohl doppelreihige Stiftleisten mit 2,54 mm Rastermaß, als auch Flachbandkabel mit 1,27 mm Rastermaß direkt anlöten lassen. Mit geeignet dünnem Leiterplattenmaterial (1 mm) lassen sich sogar Pfostensteckverbinder anlöten. In der Library sind momentan Verbinder von 2x3 bis 2x7 angelegt. <gallery> Datei:Simplecon.png|Beispiel 3x2 Datei:Simplecon.jpg|3x2 mit Steckerleiste und Flachbandkabel </gallery> Achtung: im zweiten Bild ist die Anordnung noch gespiegelt, in der Library ist die Anordnung so, dass die Pin 1-Markierung angelöteter Stecker richtig ist. [[Darei:Simplecon.zip]] [[Kategorie:Sonstiges]] [[Kategorie:EAGLE]] 455631c7e0165f7015513551a639af212e802f24 895 894 2014-05-21T04:19:32Z Chris 2 Dateilink wirklich korrigiert (Danke, Tablet...) wikitext text/x-wiki Über die Zeit sind bei mir einige Bibliotheken für EAGLE entstanden. Damit sie nicht nur auf meiner Festplatte ihr Dasein fristen und dem ein oder anderen die Arbeit erleichtern, hier zukünftig tendenziell wachsende Auswahl meiner Libs: = Konnektoren = == Simplecon == Mit dieser Bibliothek können Stiftleisten an der Kante platziert werden. Die Pads sind versetzt angeordnet, sodass sich sowohl doppelreihige Stiftleisten mit 2,54 mm Rastermaß, als auch Flachbandkabel mit 1,27 mm Rastermaß direkt anlöten lassen. Mit geeignet dünnem Leiterplattenmaterial (1 mm) lassen sich sogar Pfostensteckverbinder anlöten. In der Library sind momentan Verbinder von 2x3 bis 2x7 angelegt. <gallery> Datei:Simplecon.png|Beispiel 3x2 Datei:Simplecon.jpg|3x2 mit Steckerleiste und Flachbandkabel </gallery> Achtung: im zweiten Bild ist die Anordnung noch gespiegelt, in der Library ist die Anordnung so, dass die Pin 1-Markierung angelöteter Stecker richtig ist. [[Datei:Simplecon.zip]] [[Kategorie:Sonstiges]] [[Kategorie:EAGLE]] 2386deba64d20de4dc3c54b31bed625c5ad67a3a Hobbyelektronik.org:Impressum 4 4 896 855 2014-06-01T19:24:03Z Chris 2 ICQ verwendet kein Schwein mehr, dafür gibt's jetzt Crypto! wikitext text/x-wiki == Hauptverantwortlicher == [[Benutzer:Chris|Christof Rueß B.Eng.]]<br/> St.-Wendelin-Str. 9<br>89264 Weißenhorn<br/> E-Mail: chris at hobbyelektronik punkt org<br/> Verschlüsselt: chris-crypt at hobbyelektronik punkt org, [http://hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen)<br/> == Mitwirkende == [[Benutzer:Robert|Robert Obermayer]]<br>E-Mail: robert at hobbyelektronik punkt org<br>ICQ: [http://www.icq.com/people/about_me.php?uin=78202589 78202589] == Kontakt == Wenn du Fragen an uns hast, lies bitte zuerst nochmal die Seite, zu der du die Frage hast und dann evtl. nochmal die [[FAQ]].<br>Am einfachsten und am unkompliziertesten ist der Kontakt per E-Mail.<br>Um Spams ein bisschen einzuschränken, dürftest du auf der Homepage hier keine klickbaren Links finden. Wie man an die Adresse kommt, muss (so denke ich) nicht erklärt werden. Bitte beachte auch die Seite [[Hobbyelektronik.org:Über Hobbyelektronik.org|Über Hobbyelektronik.org]], auf der insbesondere der Haftungsausschluss zu beachten ist! a6882183d0a6feae9ce1ca37d1f143f9732f721b MediaWiki:Geshi.css 8 368 897 2014-06-09T11:46:13Z Qsysopr 1 fonts sind viel zu klein css text/css /* CSS in dieser MediaWiki-Systemnachricht wird auf die GeSHi-Syntaxhervorhebung angewendet */ .mw-geshi { font-size: 1.2 em; } 753332c8a39e4237ead7c185bfd553b676d28295 898 897 2014-06-09T11:46:58Z Qsysopr 1 css text/css /* CSS in dieser MediaWiki-Systemnachricht wird auf die GeSHi-Syntaxhervorhebung angewendet */ .mw-geshi { font-size: 1.2 em !important; } bc968d6eff067502f57a149811602e832f93ed6e 899 898 2014-06-09T11:49:06Z Qsysopr 1 css text/css /* CSS in dieser MediaWiki-Systemnachricht wird auf die GeSHi-Syntaxhervorhebung angewendet */ div.mw-geshi div,pre { font-family: Consolas, monospace !important; font-size:10pt; } d4188854a10dd22e0e98a4d3d2018b5f49d42a0a 900 899 2014-06-09T11:49:49Z Qsysopr 1 css text/css /* CSS in dieser MediaWiki-Systemnachricht wird auf die GeSHi-Syntaxhervorhebung angewendet */ div.mw-geshi div,pre { font-family: Consolas, monospace !important; font-size:12pt; } 1f0ef0387f7a5c296824246a8d0b33b07df77850 901 900 2014-06-09T11:50:08Z Qsysopr 1 css text/css /* CSS in dieser MediaWiki-Systemnachricht wird auf die GeSHi-Syntaxhervorhebung angewendet */ div.mw-geshi div,pre { font-family: Consolas, monospace !important; font-size:10pt; } d4188854a10dd22e0e98a4d3d2018b5f49d42a0a 902 901 2014-06-09T11:51:11Z Qsysopr 1 css text/css /* CSS in dieser MediaWiki-Systemnachricht wird auf die GeSHi-Syntaxhervorhebung angewendet */ div.mw-geshi div,pre { font-family: Consolas, monospace !important; font-size:10pt; background-color: #F9F9F9; border: 1px dashed #2F6FAB; } 5cc2f403622a2898b03097775b1961de13a9a544 903 902 2014-06-09T11:51:39Z Qsysopr 1 css text/css /* CSS in dieser MediaWiki-Systemnachricht wird auf die GeSHi-Syntaxhervorhebung angewendet */ div.mw-geshi div,pre { font-family: Consolas, monospace !important; font-size:10pt; background-color: #F9F9F9; border: 1px dashed #2F6FAB; padding: 1em; } 0707e1dcafc243e9192f59ec429b6c5333331c7d VBus-Decoder 0 120 904 659 2014-06-09T11:53:50Z Chris 2 /* Software */ Code-highlighting aktiviert wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] 17684e94ae4b9c1aeb8b9fec1ef69dc83559836e Kühlung für Zhongdi ZD-393L 0 369 906 2014-06-24T19:05:30Z Qsysopr 1 verschob „[[Kühlung für Zhongdi ZD-393L]]“ nach „[[Kühlung für Zhongdi ZD-933L]]“: Zahlendreher wikitext text/x-wiki #WEITERLEITUNG [[Kühlung für Zhongdi ZD-933L]] 92c1cc2b4199d50074fb90b7b626f7b9e64bbe15 909 906 2014-06-24T19:06:40Z Qsysopr 1 -.- wikitext text/x-wiki #WEITERLEITUNG [[Kühlung für Zhongdi ZD-939L]] 8ad83c694ff2d9940d7e43b3f6195668175e09c0 Raspberry Pi IO 0 304 912 829 2014-07-26T07:12:09Z Chris 2 Ergänzung für den Panana Pi wikitext text/x-wiki [[Datei:Raspberry io.jpg|200px|thumb|Raspberry Pi mit angeschlossenen LEDs]] Ich war einer der glücklichen, die einen der [http://hobbyelektronik.org/b/2012/04/er-ist-d/ ersten] [http://www.raspberrypi.org/ Raspberry Pi]s ergattern konnte. Zu meiner Schande muss ich gestehen, dass ich relativ lange gezögert habe, mich intensiver mit dem Computerchen zu beschäftigen. Interessant für Bastler ist auf jeden Fall die anschließbare Peripherie. Neben UART, SPI und I²C (für letztere existieren noch keine Treiber und ich bin leider noch zu blöd welche zu schreiben) existieren auch frei belegbare [http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 GPIOs] auf dem Board. =Erster Test= Das [http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29 Beispielprogramm] erfüllt seinen Zweck sehr gut. Nach ein wenig Herumspielen wollte ich wissen, wie schnell man denn die Bits wackeln lassen kann. Eine kleinere Änderung im Source lässt GPIO17 (bzw. "GPIO 0" an der Steckerbelegung - ich möchte nicht wissen, wer auf diese missverständliche Namensgebung gekommen ist) mit nahezu maximaler Frequenz 1000 Mal ein- und ausschalten. <source lang="c"> for (rep=0; rep<1000; rep++) { GPIO_SET = 1<<17; GPIO_CLR = 1<<17; } </source> Mit den Shellbefehlen <pre> gcc io.c sudo ./a.out </pre> Lässt sich der Code kompilieren und anschließend ausführen. Der Logic-Analyzer misst knapp 77ns Periodendauer, also 13MHz wobei ab und zu geringfügig größere Pausen entstehen, die die Frequenz auf 11MHz absinken lassen. Das ist trotzdem ganz respektabel! =Das Problem mit root= Das Beispielprogramm funktioniert also super, solange man es als root ausführt. Hinsichtlich der Sicherheit ist das jedoch etwas ungeschickt - wer möchte seine Programme dauerhaft als root ausführen? Besonders für mein Vorhaben eine ganz schlechte Idee: ich möchte als kleine Demonstration LEDs per Browser schalten lassen. Gleichzeitig verbietet der gesunde Menschenverstand, einen Webserver oder gar PHP als root-User laufen zu lassen (besonders in Hinblick auf die [http://heise.de/-1567906 schlechte] [http://heise.de/-1567433 Presse] in den letzten Tagen). Auch das /dev/mem-Interface möchte man nicht unbedingt fürs Userland freigeben (was zudem auch nicht funktioniert). Glücklicherweise kann man auf die GPIOs einzeln über virtuelle Dateien zugreifen. Das ist zwar nicht ganz so schnell, dafür kann man die virtuellen Dateien "normalen" Benutzern zugänglich machen. Dieses Zugänglichmachen findet für jeden Pin in 4 Schritten statt (hier am Beispiel von GPIO17): <pre> sudo echo "17" > /sys/class/gpio/export sudo echo "out" > /sys/class/gpio/gpio17/direction sudo chmod 666 /sys/class/gpio/gpio17/value sudo chmod 666 /sys/class/gpio/gpio17/direction </pre> Die letzten beiden Zeilen erlauben Lese- und Schreibzugriff für Besitzer (root), Gruppe (root) und jeden anderen. Alternativ kann man auch mit chown den Besitzer bzw. die Gruppe ändern, sodass man keinen Zugriff für jeden geben muss. In meinem Fall ist es aber (noch) egal. Um alle Ports auf einmal "freizugeben" habe ich eine kleines Shell-Script geschrieben, die dies erledigt: <pre> #!/bin/sh echo "17" > /sys/class/gpio/export echo "18" > /sys/class/gpio/export echo "21" > /sys/class/gpio/export echo "22" > /sys/class/gpio/export echo "23" > /sys/class/gpio/export echo "24" > /sys/class/gpio/export echo "25" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction echo "out" > /sys/class/gpio/gpio18/direction echo "out" > /sys/class/gpio/gpio21/direction echo "out" > /sys/class/gpio/gpio22/direction echo "out" > /sys/class/gpio/gpio23/direction echo "out" > /sys/class/gpio/gpio24/direction echo "out" > /sys/class/gpio/gpio25/direction chmod 666 /sys/class/gpio/gpio17/value chmod 666 /sys/class/gpio/gpio18/value chmod 666 /sys/class/gpio/gpio21/value chmod 666 /sys/class/gpio/gpio22/value chmod 666 /sys/class/gpio/gpio23/value chmod 666 /sys/class/gpio/gpio24/value chmod 666 /sys/class/gpio/gpio25/value chmod 666 /sys/class/gpio/gpio17/direction chmod 666 /sys/class/gpio/gpio18/direction chmod 666 /sys/class/gpio/gpio21/direction chmod 666 /sys/class/gpio/gpio22/direction chmod 666 /sys/class/gpio/gpio23/direction chmod 666 /sys/class/gpio/gpio24/direction chmod 666 /sys/class/gpio/gpio25/direction </pre> Für alle, die Linux nicht kennen: das "#!/bin/sh" am Anfang ist kein gewöhnlicher Kommentar, sondern ein [[wpde:Shebang|Shebang]], das der Bash (also der Konsole) sagt, mit was die Datei ausgeführt werden möchte. Wichtig ist auch, dass die Zeilenenden auf Linefeed (\n) und nicht auf Carrier Return+Linefeed eingestellt sind. Jeder gute Editor (z. B. Notepad++ oder SciTE) kann das. (Noch ein kleiner Hinweis: das 666 ist nichts satanisches, sondern die Berechtigung rw-rw-rw-, die es jedem Benutzer erlaubt, die virtuellen Dateien zu lesen und schreiben. Einen großen Dank an Y.T., der mich auf einen kleinen aber eklatanten Fehler hingewiesen hat) Wichtig ist anschließend, dass die Datei vor dem Start Ausführungsrechte bekommt: <pre> chmod 770 gpio.sh </pre> Anschließend kann man sie mit dem Befehl folgendem Befehl ausführen: <pre> sudo ./gpio </pre> '''Achtung''': Die Freigabe der GPIOs ist nicht persistent. Nach einem Neustart muss das Script erneut ausgeführt werden! =Webserver= Ein grundlegendes Element fehlt noch: der Webserver, den man wahrscheinlich am einfachsten mit [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] installiert. Hier die Befehle, die ich zur Installation von [http://www.lighttpd.net/ lighttpd] mit PHP5 verwendet habe (keine Garantie auf Funktionalität, Vollständigkeit und Korrektheit): <pre> sudo groupadd www-data sudo aptitude install lighttpd sudo aptitude install php5-cgi sudo lighty-enable-mod fastcgi sudo adduser pi www-data sudo chown -R www-data:www-data /var/www sudo chmod -R 775 /var/www </pre> Lighttpd habe ich deswegen gewählt, weil er (wie der Name suggeriert) etwas leichter und schneller als der mächtigere (aber etwas schwerfällige) Apache ist. Damit PHP funktioniert, muss in der Datei /etc/lighttpd/lighttpd.conf (wenn noch nicht vorhanden) durch das Ausführen von <pre> sudo nano /etc/lighttpd/lighttpd.conf </pre> folgender Text hinzugefügt werden: <pre> fastcgi.server = ( ".php" => (( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket" ))) </pre> Nach einem Server-Neustart mit <pre> sudo /etc/init.d/lighttpd force-reload </pre> sollte der Raspberry Pi per HTTP erreichbar sein. =Software= ==Server== Wie schon erwähnt läuft auf dem Server (oder sollte zumindest) PHP laufen. Da ich es nicht mag, Seiten wegen Kleinigkeiten neu zu laden, kommt ein [[wpde:Ajax (Programmierung)|Ajax]]/[http://json.org/ JSON]-Interface zum Einsatz. Dementsprechend fällt die Serversoftware minimalistisch aus. Beispielsweise übernimmt read.php das Lesen der Ports und deren Richtung. Die Informationen werden in ein assoziatives (Name => Wert) Array geschrieben, ins JSON-Format umgewandelt und an den Client ausgegeben: <source lang="php"> <?php $bits = array(17, 18, 21, 22, 23, 24, 25); $retval = array(); for($x = 0; $x < count($bits); $x++) { $bit = $bits[$x]; $val = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/value")); $dir = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/direction")); $val = $val == "1" ? 1 : 0; $dir = $dir == "out" ? "o" : "i"; $retval[] = array("bit" => $bit, "val" => $val, "dir" => $dir); } echo json_encode($retval); </source> ==Client== Den Client habe ich relativ schnell (und etwas schlampig) in JavaScript heruntergerissen. Wer etwas JavaScript und die vielen d.ebi, d.ac, d.ce und d.ctn irritiert - das sind Abkürzungen für häufig verwendete Befehle, die ich in common.js definiert habe: <source lang="javascript"> var d = { d : document, w : window, ebi : function(i) { return document.getElementById(i); }, ebn : function(n) { return document.getElementsByName(n); }, febn : function(n) { return document.getElementsByName(n)[0]; }, ce : function(n) { return document.createElement(n); }, ctn : function(n) { return document.createTextNode(n); }, ac : function(p, c) { return p.appendChild(c); }, ac1 : function(p, c) { p.appendChild(c); return p; } } </source> d.ebi steht zum Beispiel für '''d'''ocument.get'''E'''lement'''B'''y'''I'''d d.ac für '''d'''ocument.'''a'''ppend'''C'''hild usw... In diesem Sinne auch eine Entschuldigung an alle, die bei dem Klammer-Massaker einen Knoten im Hirn bekommen ;-) Dadurch, dass nahezu alles in JavaScript gemacht wird, ist der HTML-Body gähnend leer. Erst beim Laden wird der Seite Leben eingehaucht: <gallery> Datei:raspberry_io_gui.png|Benutzerinterface </gallery> Der Code erzeugt zunächst eine Tabelle, die dann durch Objekte von GpioPin gefüllt wird. Durch Klick auf die span-Elemente bzw. Bilder wird der Inhalt umgeschaltet und per XmlHttpRequest ein Kommando an den Server geschickt. Beim Klick auf Lesen wird ebenfalls per XmlHttpRequest eine Anfrage an den Server gesendet, wie oben erwähnt, mit einem JSON-String antwortet. Dies sieht dann z. B. wie folgt aus: <pre> [{"bit":17,"val":0,"dir":"o"},{"bit":18,"val":1,"dir":"o"},{"bit":21,"val":0,"dir":"o"},{"bit":22,"val":0,"dir":"i"},{"bit":23,"val":1,"dir":"i"},{"bit":24,"val":0,"dir":"o"},{"bit":25,"val":0,"dir":"o"}] </pre> Aufgedröselt wird die Struktur deutlicher: <source lang="javascript"> [ { "bit" : 17, "val" : 0, "dir" : "o" },{ "bit" : 18, "val" : 1, "dir" : "o" },{ "bit" : 21, "val" : 0, "dir" : "o" },{ ... } ] </source> Diese wird durch den JSON-parser in ein Objekt umgewandelt, per Schleife zugeordnet und durch die Funktion GpioPin::SetVals() gesetzt. Die Richtung und Wert kann man einfach durch Klick auf das jeweilige Element verändern. Durch einen Klick auf "Refresh" kann man die tatsächlichen Werte vom Server ermitteln, nach dem Aktivieren der Checkbox geschieht dies automatisch im Sekundentakt. Getestet wurde die die Anwendung bis jetzt im Firefox, "Standard" Android-Browser und dem aktuellen IE, wobei in letzterem die Aktualisierung nicht richtig funktioniert. <gallery> Datei:Raspberry_io_android.jpg|Raspberry Pi mit Tablet </gallery> =Download= [[Datei:Raspberry Pi IO.zip]] ==Hinweise== Der Inhalt der ZIP-Datei kann relativ einfach mit FileZilla auf den Raspberry (per SSH-Filetransfer) geschoben werden. Der Order IO muss unter /var/www/ liegen, gpio.sh an einem nahezu beliebigen Ort. Vor dem Ausführen der gpio.sh nicht vergessen, die Ausführungsrechte zu setzen! =Banana Pi= Eine freundliche Ergänzung von Oli: <pre>Ich hatte das mal ausprobiert auf einen Banana PI mit Raspbian, Ging leider erst nachdem ich in der gpio.sh zum schluss das eingefügt habe. Nur zur Ergänzung:</pre> <pre>chgrp -R www-data /sys/class/gpio chmod -R g+rw /sys/class/gpio </pre> [[Kategorie:PC]] [[Kategorie:Raspberry Pi]] 74afd2d4e0ea9574d1a7b8f22df17e7559e8cd17 913 912 2014-07-26T07:12:40Z Chris 2 Satzbau/Wortwahl wikitext text/x-wiki [[Datei:Raspberry io.jpg|200px|thumb|Raspberry Pi mit angeschlossenen LEDs]] Ich war einer der glücklichen, die einen der [http://hobbyelektronik.org/b/2012/04/er-ist-d/ ersten] [http://www.raspberrypi.org/ Raspberry Pi]s ergattern konnte. Zu meiner Schande muss ich gestehen, dass ich relativ lange gezögert habe, mich intensiver mit dem Computerchen zu beschäftigen. Interessant für Bastler ist auf jeden Fall die anschließbare Peripherie. Neben UART, SPI und I²C (für letztere existieren noch keine Treiber und ich bin leider noch zu blöd welche zu schreiben) existieren auch frei belegbare [http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 GPIOs] auf dem Board. =Erster Test= Das [http://elinux.org/Rpi_Low-level_peripherals#GPIO_Driving_Example_.28C.29 Beispielprogramm] erfüllt seinen Zweck sehr gut. Nach ein wenig Herumspielen wollte ich wissen, wie schnell man denn die Bits wackeln lassen kann. Eine kleinere Änderung im Source lässt GPIO17 (bzw. "GPIO 0" an der Steckerbelegung - ich möchte nicht wissen, wer auf diese missverständliche Namensgebung gekommen ist) mit nahezu maximaler Frequenz 1000 Mal ein- und ausschalten. <source lang="c"> for (rep=0; rep<1000; rep++) { GPIO_SET = 1<<17; GPIO_CLR = 1<<17; } </source> Mit den Shellbefehlen <pre> gcc io.c sudo ./a.out </pre> Lässt sich der Code kompilieren und anschließend ausführen. Der Logic-Analyzer misst knapp 77ns Periodendauer, also 13MHz wobei ab und zu geringfügig größere Pausen entstehen, die die Frequenz auf 11MHz absinken lassen. Das ist trotzdem ganz respektabel! =Das Problem mit root= Das Beispielprogramm funktioniert also super, solange man es als root ausführt. Hinsichtlich der Sicherheit ist das jedoch etwas ungeschickt - wer möchte seine Programme dauerhaft als root ausführen? Besonders für mein Vorhaben eine ganz schlechte Idee: ich möchte als kleine Demonstration LEDs per Browser schalten lassen. Gleichzeitig verbietet der gesunde Menschenverstand, einen Webserver oder gar PHP als root-User laufen zu lassen (besonders in Hinblick auf die [http://heise.de/-1567906 schlechte] [http://heise.de/-1567433 Presse] in den letzten Tagen). Auch das /dev/mem-Interface möchte man nicht unbedingt fürs Userland freigeben (was zudem auch nicht funktioniert). Glücklicherweise kann man auf die GPIOs einzeln über virtuelle Dateien zugreifen. Das ist zwar nicht ganz so schnell, dafür kann man die virtuellen Dateien "normalen" Benutzern zugänglich machen. Dieses Zugänglichmachen findet für jeden Pin in 4 Schritten statt (hier am Beispiel von GPIO17): <pre> sudo echo "17" > /sys/class/gpio/export sudo echo "out" > /sys/class/gpio/gpio17/direction sudo chmod 666 /sys/class/gpio/gpio17/value sudo chmod 666 /sys/class/gpio/gpio17/direction </pre> Die letzten beiden Zeilen erlauben Lese- und Schreibzugriff für Besitzer (root), Gruppe (root) und jeden anderen. Alternativ kann man auch mit chown den Besitzer bzw. die Gruppe ändern, sodass man keinen Zugriff für jeden geben muss. In meinem Fall ist es aber (noch) egal. Um alle Ports auf einmal "freizugeben" habe ich eine kleines Shell-Script geschrieben, die dies erledigt: <pre> #!/bin/sh echo "17" > /sys/class/gpio/export echo "18" > /sys/class/gpio/export echo "21" > /sys/class/gpio/export echo "22" > /sys/class/gpio/export echo "23" > /sys/class/gpio/export echo "24" > /sys/class/gpio/export echo "25" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio17/direction echo "out" > /sys/class/gpio/gpio18/direction echo "out" > /sys/class/gpio/gpio21/direction echo "out" > /sys/class/gpio/gpio22/direction echo "out" > /sys/class/gpio/gpio23/direction echo "out" > /sys/class/gpio/gpio24/direction echo "out" > /sys/class/gpio/gpio25/direction chmod 666 /sys/class/gpio/gpio17/value chmod 666 /sys/class/gpio/gpio18/value chmod 666 /sys/class/gpio/gpio21/value chmod 666 /sys/class/gpio/gpio22/value chmod 666 /sys/class/gpio/gpio23/value chmod 666 /sys/class/gpio/gpio24/value chmod 666 /sys/class/gpio/gpio25/value chmod 666 /sys/class/gpio/gpio17/direction chmod 666 /sys/class/gpio/gpio18/direction chmod 666 /sys/class/gpio/gpio21/direction chmod 666 /sys/class/gpio/gpio22/direction chmod 666 /sys/class/gpio/gpio23/direction chmod 666 /sys/class/gpio/gpio24/direction chmod 666 /sys/class/gpio/gpio25/direction </pre> Für alle, die Linux nicht kennen: das "#!/bin/sh" am Anfang ist kein gewöhnlicher Kommentar, sondern ein [[wpde:Shebang|Shebang]], das der Bash (also der Konsole) sagt, mit was die Datei ausgeführt werden möchte. Wichtig ist auch, dass die Zeilenenden auf Linefeed (\n) und nicht auf Carrier Return+Linefeed eingestellt sind. Jeder gute Editor (z. B. Notepad++ oder SciTE) kann das. (Noch ein kleiner Hinweis: das 666 ist nichts satanisches, sondern die Berechtigung rw-rw-rw-, die es jedem Benutzer erlaubt, die virtuellen Dateien zu lesen und schreiben. Einen großen Dank an Y.T., der mich auf einen kleinen aber eklatanten Fehler hingewiesen hat) Wichtig ist anschließend, dass die Datei vor dem Start Ausführungsrechte bekommt: <pre> chmod 770 gpio.sh </pre> Anschließend kann man sie mit dem Befehl folgendem Befehl ausführen: <pre> sudo ./gpio </pre> '''Achtung''': Die Freigabe der GPIOs ist nicht persistent. Nach einem Neustart muss das Script erneut ausgeführt werden! =Webserver= Ein grundlegendes Element fehlt noch: der Webserver, den man wahrscheinlich am einfachsten mit [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] installiert. Hier die Befehle, die ich zur Installation von [http://www.lighttpd.net/ lighttpd] mit PHP5 verwendet habe (keine Garantie auf Funktionalität, Vollständigkeit und Korrektheit): <pre> sudo groupadd www-data sudo aptitude install lighttpd sudo aptitude install php5-cgi sudo lighty-enable-mod fastcgi sudo adduser pi www-data sudo chown -R www-data:www-data /var/www sudo chmod -R 775 /var/www </pre> Lighttpd habe ich deswegen gewählt, weil er (wie der Name suggeriert) etwas leichter und schneller als der mächtigere (aber etwas schwerfällige) Apache ist. Damit PHP funktioniert, muss in der Datei /etc/lighttpd/lighttpd.conf (wenn noch nicht vorhanden) durch das Ausführen von <pre> sudo nano /etc/lighttpd/lighttpd.conf </pre> folgender Text hinzugefügt werden: <pre> fastcgi.server = ( ".php" => (( "bin-path" => "/usr/bin/php5-cgi", "socket" => "/tmp/php.socket" ))) </pre> Nach einem Server-Neustart mit <pre> sudo /etc/init.d/lighttpd force-reload </pre> sollte der Raspberry Pi per HTTP erreichbar sein. =Software= ==Server== Wie schon erwähnt läuft auf dem Server (oder sollte zumindest) PHP laufen. Da ich es nicht mag, Seiten wegen Kleinigkeiten neu zu laden, kommt ein [[wpde:Ajax (Programmierung)|Ajax]]/[http://json.org/ JSON]-Interface zum Einsatz. Dementsprechend fällt die Serversoftware minimalistisch aus. Beispielsweise übernimmt read.php das Lesen der Ports und deren Richtung. Die Informationen werden in ein assoziatives (Name => Wert) Array geschrieben, ins JSON-Format umgewandelt und an den Client ausgegeben: <source lang="php"> <?php $bits = array(17, 18, 21, 22, 23, 24, 25); $retval = array(); for($x = 0; $x < count($bits); $x++) { $bit = $bits[$x]; $val = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/value")); $dir = trim(@shell_exec("cat /sys/class/gpio/gpio".$bit."/direction")); $val = $val == "1" ? 1 : 0; $dir = $dir == "out" ? "o" : "i"; $retval[] = array("bit" => $bit, "val" => $val, "dir" => $dir); } echo json_encode($retval); </source> ==Client== Den Client habe ich relativ schnell (und etwas schlampig) in JavaScript heruntergerissen. Wer etwas JavaScript und die vielen d.ebi, d.ac, d.ce und d.ctn irritiert - das sind Abkürzungen für häufig verwendete Befehle, die ich in common.js definiert habe: <source lang="javascript"> var d = { d : document, w : window, ebi : function(i) { return document.getElementById(i); }, ebn : function(n) { return document.getElementsByName(n); }, febn : function(n) { return document.getElementsByName(n)[0]; }, ce : function(n) { return document.createElement(n); }, ctn : function(n) { return document.createTextNode(n); }, ac : function(p, c) { return p.appendChild(c); }, ac1 : function(p, c) { p.appendChild(c); return p; } } </source> d.ebi steht zum Beispiel für '''d'''ocument.get'''E'''lement'''B'''y'''I'''d d.ac für '''d'''ocument.'''a'''ppend'''C'''hild usw... In diesem Sinne auch eine Entschuldigung an alle, die bei dem Klammer-Massaker einen Knoten im Hirn bekommen ;-) Dadurch, dass nahezu alles in JavaScript gemacht wird, ist der HTML-Body gähnend leer. Erst beim Laden wird der Seite Leben eingehaucht: <gallery> Datei:raspberry_io_gui.png|Benutzerinterface </gallery> Der Code erzeugt zunächst eine Tabelle, die dann durch Objekte von GpioPin gefüllt wird. Durch Klick auf die span-Elemente bzw. Bilder wird der Inhalt umgeschaltet und per XmlHttpRequest ein Kommando an den Server geschickt. Beim Klick auf Lesen wird ebenfalls per XmlHttpRequest eine Anfrage an den Server gesendet, wie oben erwähnt, mit einem JSON-String antwortet. Dies sieht dann z. B. wie folgt aus: <pre> [{"bit":17,"val":0,"dir":"o"},{"bit":18,"val":1,"dir":"o"},{"bit":21,"val":0,"dir":"o"},{"bit":22,"val":0,"dir":"i"},{"bit":23,"val":1,"dir":"i"},{"bit":24,"val":0,"dir":"o"},{"bit":25,"val":0,"dir":"o"}] </pre> Aufgedröselt wird die Struktur deutlicher: <source lang="javascript"> [ { "bit" : 17, "val" : 0, "dir" : "o" },{ "bit" : 18, "val" : 1, "dir" : "o" },{ "bit" : 21, "val" : 0, "dir" : "o" },{ ... } ] </source> Diese wird durch den JSON-parser in ein Objekt umgewandelt, per Schleife zugeordnet und durch die Funktion GpioPin::SetVals() gesetzt. Die Richtung und Wert kann man einfach durch Klick auf das jeweilige Element verändern. Durch einen Klick auf "Refresh" kann man die tatsächlichen Werte vom Server ermitteln, nach dem Aktivieren der Checkbox geschieht dies automatisch im Sekundentakt. Getestet wurde die die Anwendung bis jetzt im Firefox, "Standard" Android-Browser und dem aktuellen IE, wobei in letzterem die Aktualisierung nicht richtig funktioniert. <gallery> Datei:Raspberry_io_android.jpg|Raspberry Pi mit Tablet </gallery> =Download= [[Datei:Raspberry Pi IO.zip]] ==Hinweise== Der Inhalt der ZIP-Datei kann relativ einfach mit FileZilla auf den Raspberry (per SSH-Filetransfer) geschoben werden. Der Order IO muss unter /var/www/ liegen, gpio.sh an einem nahezu beliebigen Ort. Vor dem Ausführen der gpio.sh nicht vergessen, die Ausführungsrechte zu setzen! =Banana Pi= Ein freundlicher Hinweis von Oli: <pre>Ich hatte das mal ausprobiert auf einen Banana PI mit Raspbian, Ging leider erst nachdem ich in der gpio.sh zum schluss das eingefügt habe. Nur zur Ergänzung:</pre> <pre>chgrp -R www-data /sys/class/gpio chmod -R g+rw /sys/class/gpio </pre> [[Kategorie:PC]] [[Kategorie:Raspberry Pi]] 6308a88a540b2898391a41991a4768d2eef4603f Datei:ITP Gesamt.jpg 6 370 914 2014-08-24T19:17:03Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 928 914 2014-08-24T19:22:37Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP Gesamt.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Innenkoerper oben.jpg 6 371 915 2014-08-24T19:17:04Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 929 915 2014-08-24T19:22:38Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP Innenkoerper oben.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Innenkoerper unten.jpg 6 372 916 2014-08-24T19:17:05Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 930 916 2014-08-24T19:22:39Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP Innenkoerper unten.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Kopf.jpg 6 373 917 2014-08-24T19:17:05Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 931 917 2014-08-24T19:22:39Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP Kopf.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP LED1.jpg 6 374 918 2014-08-24T19:17:06Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 932 918 2014-08-24T19:22:40Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP LED1.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP LED2.jpg 6 375 919 2014-08-24T19:17:07Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 933 919 2014-08-24T19:22:41Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP LED2.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP LED3.jpg 6 376 920 2014-08-24T19:17:08Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Leitungsbruch1.jpg 6 377 921 2014-08-24T19:17:08Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Leitungsbruch2.jpg 6 378 922 2014-08-24T19:17:09Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Leitungsbruch3.jpg 6 379 923 2014-08-24T19:17:12Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Waermeleitpaste.jpg 6 380 924 2014-08-24T19:17:13Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Zusammenbau1.jpg 6 381 925 2014-08-24T19:17:14Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Zusammenbau2.jpg 6 382 926 2014-08-24T19:17:15Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Zusammenbau3.jpg 6 383 927 2014-08-24T19:17:16Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP LED3.jpg 6 376 934 920 2014-08-24T19:22:42Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP LED3.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Leitungsbruch1.jpg 6 377 935 921 2014-08-24T19:22:42Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP Leitungsbruch1.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Leitungsbruch2.jpg 6 378 936 922 2014-08-24T19:22:43Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP Leitungsbruch2.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Leitungsbruch3.jpg 6 379 937 923 2014-08-24T19:22:44Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP Leitungsbruch3.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP oeffnen.jpg 6 384 938 2014-08-24T19:22:44Z Qsysopr 1 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Waermeleitpaste.jpg 6 380 939 924 2014-08-24T19:22:45Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP Waermeleitpaste.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Zusammenbau1.jpg 6 381 940 925 2014-08-24T19:22:46Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP Zusammenbau1.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Zusammenbau2.jpg 6 382 941 926 2014-08-24T19:22:46Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP Zusammenbau2.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ITP Zusammenbau3.jpg 6 383 942 927 2014-08-24T19:22:47Z Qsysopr 1 lud eine neue Version von „[[Datei:ITP Zusammenbau3.jpg]]“ hoch: MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Reparatur iTP A3 EOS 0 385 943 2014-08-24T19:33:17Z Chris 2 Artikel erstellt wikitext text/x-wiki [[Datei:iTP_Gesamt.jpg|thumb|iTP A3 EOS im Vergleich zu einer AA-Zelle]] Vor ein paar Jahren habe ich mir eine iTP A3 EOS (upgraded) zugelegt. Wem die Bezeichnung nichts sagt: keine Sorge, muss man nicht kennen - es handelt sich dabei um eine Taschenlampe. Sie hat bis zu 96 Lumen (in 3 Stufen), obwohl sie nicht besonders größer als eine AA-Batterie ist (14 mm Durchmesser, 67 mm lang). Versorgt wird sie durch eine einzelne AAA-Zelle wobei der eingebaute Schaltwandler bis knapp 0,9 Volt läuft. Er holt also fast alles aus der Zelle, auch wenn die Taschenlampe zum Ende hin etwas dunkler wird. Das Teil ist - wie so vieles - toll, solange es funktioniert. Nachdem das Lämpchen immer am Schlüsselbund ist und dementsprechend öfter mal runter fiel, war nach knapp drei Jahren Schluss. Erst ging sie erst nach zudrehen und anschnippen an, später musste man etwas klopfen, dann blieb sie dauerhaft aus. Grmpf. Wegwerfen? Auf keinen Fall! Zumal es sie anscheinend nicht mehr zu Kaufen gibt. = Auf das Ding! = Das wahrscheinlich schwierigste Unterfangen an der Reparatur - Der Kopf der Lampe ist schnell drunten, aber wie kommt man an die Elektronik? Zwei Löcher in der Leiterkarte und das Gewinde verraten den Trick: Rausschrauben. Dazu nimmt man am besten eine ältere und sehr stabile Pinzette oder spannt zwei passende Stahlstifte (am besten mit Absatz oder konisch, damit man innen nichts aufspießt) in einen Schraubstock. <gallery> Datei:iTP_Kopf.jpg|Taschenlampenkopf von hinten Datei:iTP_oeffnen.jpg|Einrasten & Drehen </gallery> Erschwerend kommt dazu, dass der Innenkörper mit dem Lampenkopf verklebt wurde. Dagegen arbeitet man am besten mit Wärme und sanfter Gewalt. Es hilft auch, den Innenkörper immer wieder ein Stück hineinzudrehen. Hat man das Innenleben befreit, ist es empfehlenswert, die Klebereste vollständig zu entfernen - sowohl am Innenteil als auch am Lampenkopf. Sonst wird das Einschrauben später noch schwieriger. Dazu am Besten wieder erwärmen und vorsichtig (das Alu ist relativ weich) die Gewindegänge auskratzen. <gallery> Datei:iTP_Innenkoerper_oben.jpg|Helle Seite... Datei:iTP_Innenkoerper_unten.jpg|...und dunkle Seite des Innenkörpers </gallery> Um an die Elektronik zu kommen, muss zunächst die Leiterkarte runter, die zugleich den Kontakt zur Batterie darstellt. Dazu geht man am besten mit einem feinen Schraubendreher in die Nut und hebelt sie vorsichtig heraus. Wärme hilft auch hier gegen den Kleber. Oft sieht man nach diesem Schritt schon den Defekt: <gallery> Datei:iTP_Leitungsbruch1.jpg Datei:iTP_Leitungsbruch2.jpg Datei:iTP_Leitungsbruch3.jpg </gallery> Leitungsbruch. = Reparatur = Damit das Löten einfacher vonstatten geht (es ist verdammt eng!) habe ich bei meinen beiden Reparaturen auch die LED herausgenommen. Dazu muss man auf der anderen Seite des Innenteils zuerst die Plastikabdeckung herausnehmen und anschließend die Anschlussdrähte ablöten. <gallery> Datei:iTP_LED1.jpg|Mit Deckel Datei:iTP_LED2.jpg|Ohne Deckel Datei:iTP_LED3.jpg|Ohne LED </gallery> Da die Wärmeleitpaste eh eingetrocknet ist, kann man sie auch gleich entfernen/erneuern. Isopropanol und Wattestäbchen sind hier die Mittel der Wahl. Wenn man das Teil schon einmal offen hat: Am besten beide Leitungen zum Batteriekontakt tauschen! Ich habe bei der ersten Reparatur vor einem halben Jahr den Fehler gemacht, nur die gebrochene Leitung neu anzulöten und durfte das Teil jetzt noch einmal öffnen. Die beiden Litzen sind recht kurz zu halten, 1 cm ist mehr als genug. Auf jeden Fall sollte man eine feine Litze nehmen (meine ist schon fast zu dick), damit die Lötstellen nicht wieder so schnell brechen. = Zusammenbau = Und schon liegt das Teil wieder da wie eine aufgebrachte Krabbe - bis man es wieder in die Behausung steckt: <gallery> Datei:iTP_Zusammenbau1.jpg|[http://www.youtube.com/results?search_query=findet+nemo+krabben+hey Hey!] Datei:iTP_Zusammenbau2.jpg|Zusammengeklappt Datei:iTP_Zusammenbau3.jpg|und wieder eingebaut </gallery> Wichtig beim Zusammenbau: die Drähte für die LED durch die Löcher stecken und dann die Elektronik um 180 Grad drehen, sonst schauen die Drähte viel zu weit heraus. (Alternativ: zuerst LED anlöten und dann die Elektronik ins Alugehäuse einsetzen) Die vorher entfernte Wärmeleitpaste durch neue ersetzt (wie beim PC gilt: weniger ist manchmal mehr und bei mir ist es fast schon zu viel) und schon kann man die LED wieder anlöten. Wichtig hierbei: die Drähte müssen gegen den Uhrzeigersinn liegen (siehe oben), sonst passt die Plastikkappe nicht! Die Kontaktplatine wieder eingedrückt (wenn sie fest hält, muss man sie nicht einmal verkleben) kann das Modul wieder ins Gehäuse. Und sie leuchtet wieder! [[Kategorie:Elektronik]] [[Kategorie:Reparatur]] 8d34a4e04297bc5c572f240ea1fd155e7bbb3831 945 943 2014-08-24T19:37:23Z Chris 2 /* Zusammenbau */ wikitext text/x-wiki [[Datei:iTP_Gesamt.jpg|thumb|iTP A3 EOS im Vergleich zu einer AA-Zelle]] Vor ein paar Jahren habe ich mir eine iTP A3 EOS (upgraded) zugelegt. Wem die Bezeichnung nichts sagt: keine Sorge, muss man nicht kennen - es handelt sich dabei um eine Taschenlampe. Sie hat bis zu 96 Lumen (in 3 Stufen), obwohl sie nicht besonders größer als eine AA-Batterie ist (14 mm Durchmesser, 67 mm lang). Versorgt wird sie durch eine einzelne AAA-Zelle wobei der eingebaute Schaltwandler bis knapp 0,9 Volt läuft. Er holt also fast alles aus der Zelle, auch wenn die Taschenlampe zum Ende hin etwas dunkler wird. Das Teil ist - wie so vieles - toll, solange es funktioniert. Nachdem das Lämpchen immer am Schlüsselbund ist und dementsprechend öfter mal runter fiel, war nach knapp drei Jahren Schluss. Erst ging sie erst nach zudrehen und anschnippen an, später musste man etwas klopfen, dann blieb sie dauerhaft aus. Grmpf. Wegwerfen? Auf keinen Fall! Zumal es sie anscheinend nicht mehr zu Kaufen gibt. = Auf das Ding! = Das wahrscheinlich schwierigste Unterfangen an der Reparatur - Der Kopf der Lampe ist schnell drunten, aber wie kommt man an die Elektronik? Zwei Löcher in der Leiterkarte und das Gewinde verraten den Trick: Rausschrauben. Dazu nimmt man am besten eine ältere und sehr stabile Pinzette oder spannt zwei passende Stahlstifte (am besten mit Absatz oder konisch, damit man innen nichts aufspießt) in einen Schraubstock. <gallery> Datei:iTP_Kopf.jpg|Taschenlampenkopf von hinten Datei:iTP_oeffnen.jpg|Einrasten & Drehen </gallery> Erschwerend kommt dazu, dass der Innenkörper mit dem Lampenkopf verklebt wurde. Dagegen arbeitet man am besten mit Wärme und sanfter Gewalt. Es hilft auch, den Innenkörper immer wieder ein Stück hineinzudrehen. Hat man das Innenleben befreit, ist es empfehlenswert, die Klebereste vollständig zu entfernen - sowohl am Innenteil als auch am Lampenkopf. Sonst wird das Einschrauben später noch schwieriger. Dazu am Besten wieder erwärmen und vorsichtig (das Alu ist relativ weich) die Gewindegänge auskratzen. <gallery> Datei:iTP_Innenkoerper_oben.jpg|Helle Seite... Datei:iTP_Innenkoerper_unten.jpg|...und dunkle Seite des Innenkörpers </gallery> Um an die Elektronik zu kommen, muss zunächst die Leiterkarte runter, die zugleich den Kontakt zur Batterie darstellt. Dazu geht man am besten mit einem feinen Schraubendreher in die Nut und hebelt sie vorsichtig heraus. Wärme hilft auch hier gegen den Kleber. Oft sieht man nach diesem Schritt schon den Defekt: <gallery> Datei:iTP_Leitungsbruch1.jpg Datei:iTP_Leitungsbruch2.jpg Datei:iTP_Leitungsbruch3.jpg </gallery> Leitungsbruch. = Reparatur = Damit das Löten einfacher vonstatten geht (es ist verdammt eng!) habe ich bei meinen beiden Reparaturen auch die LED herausgenommen. Dazu muss man auf der anderen Seite des Innenteils zuerst die Plastikabdeckung herausnehmen und anschließend die Anschlussdrähte ablöten. <gallery> Datei:iTP_LED1.jpg|Mit Deckel Datei:iTP_LED2.jpg|Ohne Deckel Datei:iTP_LED3.jpg|Ohne LED </gallery> Da die Wärmeleitpaste eh eingetrocknet ist, kann man sie auch gleich entfernen/erneuern. Isopropanol und Wattestäbchen sind hier die Mittel der Wahl. Wenn man das Teil schon einmal offen hat: Am besten beide Leitungen zum Batteriekontakt tauschen! Ich habe bei der ersten Reparatur vor einem halben Jahr den Fehler gemacht, nur die gebrochene Leitung neu anzulöten und durfte das Teil jetzt noch einmal öffnen. Die beiden Litzen sind recht kurz zu halten, 1 cm ist mehr als genug. Auf jeden Fall sollte man eine feine Litze nehmen (meine ist schon fast zu dick), damit die Lötstellen nicht wieder so schnell brechen. = Zusammenbau = Und schon liegt das Teil wieder da wie eine aufgebrachte Krabbe - bis man es wieder in die Behausung steckt: <gallery> Datei:iTP_Zusammenbau1.jpg|[http://www.youtube.com/results?search_query=findet+nemo+krabben+hey Hey!] Datei:iTP_Zusammenbau2.jpg|Zusammengeklappt Datei:iTP_Zusammenbau3.jpg|und wieder eingebaut </gallery> Wichtig beim Zusammenbau: die Drähte für die LED durch die Löcher stecken und dann die Elektronik um 180 Grad drehen, sonst schauen die Drähte viel zu weit heraus. (Alternativ: zuerst LED anlöten und dann die Elektronik ins Alugehäuse einsetzen) Die vorher entfernte Wärmeleitpaste durch neue ersetzt (wie beim PC gilt: weniger ist manchmal mehr und bei mir ist es fast schon zu viel) und schon kann man die LED wieder anlöten. Beim Anlöten der Drähte an die LED müssen diese gegen den Uhrzeigersinn liegen (siehe oben), sonst passt die Plastikkappe nicht! Bei der LED sind übrigens sowohl Anode als auch Kathode auf der Trägerplatine markiert (+ und -) Die Kontaktplatine wieder eingedrückt (wenn sie fest hält, muss man sie nicht einmal verkleben) kann das Modul wieder ins Gehäuse. Und sie leuchtet wieder! [[Kategorie:Elektronik]] [[Kategorie:Reparatur]] 4470e0a000d999fe27ab18f7cd76b95596f8ed23 Hauptseite 0 1 944 911 2014-08-24T19:35:26Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *24.08.2014 [[Reparatur iTP A3 EOS]] *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] *02.02.2014 [[EAGLE-Bibliotheken]] *10.11.2013 [[Zeitraffer mit Linux]] *14.08.2013 [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 [[Farnell-Assistent]] ==Änderungen== *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio ff78e8ea702a55704de7c74519cd06873001cc28 960 944 2014-11-19T21:56:36Z Chris 2 Mal wieder was neues! wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] *02.02.2014 [[EAGLE-Bibliotheken]] *10.11.2013 [[Zeitraffer mit Linux]] *14.08.2013 [[Umbau Belkin Auto-USB-Lader]] ==Änderungen== *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio f4a94cc236c9536cd12821fc3f065b97f0059efc 980 960 2015-04-01T18:21:31Z Chris 2 Neues! wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *01.04.2015 [[Mini-Schaltwandler]] *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] *02.02.2014 [[EAGLE-Bibliotheken]] *10.11.2013 [[Zeitraffer mit Linux]] ==Änderungen== *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio af7c6f4cd8a77d14ded78ac74d93d1964336f46c Benutzer:Chris 2 45 946 854 2014-09-22T19:14:28Z Chris 2 wikitext text/x-wiki = Wie es dazu kam = Irgendwann um 2003 fing ich damit an, meine (mehr oder weniger gelungenen) Bastel-Projekte in HTML zu verwandeln und auf hobby-elektronik.de.vu zu veröffentlichen. Der Speicherplatz bei Tripod wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich irgendwann, auf das schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10 April 2005 die Domain hobbyelektronik.org registriert. Zu .org kam es, da mir eine Woche davor jemand die .net-Domain weggeschnappte. Im Nachhinein bin ich glücklich, dem damaligen .net-Hype entgangen zu sein. Eine richtige Organisation sind wir zwar noch immer nicht aber was nicht ist, kann ja noch werden ;) = Was ich mache = Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" bezeichnen. Von Oktober 2009 bis Juli 2013 habe ich Elektrotechnik/Nachrichtentechnik an der [http://www.hs-ulm.de Hochschule Ulm] studiert und Arbeite seit Oktober 2013 im Automotive-Bereich. Die Schnittmenge bzw. vielmehr die Verbindung aus den beiden Bereichen kommen auch wieder in meinen Hobbys zusammen. Seit September 2012 bin ich Kleinunternehmer und repariere nebenzu Computer, wobei ein weiterer - für Besucher dieser Homepage interessantere - Geschäftsbereich geplant ist. Abseits vom Schreibtisch findet man mich ab und zu hinter der Spiegelreflex, (viel zu selten) auf dem Rad oder in weit entfernten Ländern. Ein paar Eindrücke davon kann man auf den Fehlerseiten dieser Homepage finden. = Warum das Ganze? = Ganz einfach: Weil es mir Spaß macht. Wie an anderer Stelle schon erwähnt, bezeichne ich diese Seite als "nicht-kommerzielles Umfeld". Damit ist gemeint, dass ich mit dieser Homepage kein Geld verdiene (keine Werbung, keine Partnerschaften mir irgendwelchen Firmen, etc.) und es ehrlich gesagt auch nicht will. Das bedeutet auch, dass Produkterwähnungen und evtl. auch Empfehlungen aus meiner eigenen Erfahrung und Meinung gemacht werden. (Wer spenden will - gerne auch Sachspenden - ist natürlich willkommen ;)). Neben dem Spaß geht es mir auch darum, etwas an andere Bastler, Elektronik-Einsteiger und DICH weiter- bzw. zurückzugeben. Auch ich habe mal sehr klein angefangen und war froh um alles, was mich näher in Richtung Computer und Elektronik brachte (und auch heute noch bringt). Wenn man so will, kann man es als Kreislauf verstehen :) [http://sprut.de/misc/hpphilos.htm Sprut] hat es meiner Meinung mit seiner Homepage-Philosophie sehr gut getroffen. = Kannst du mir... = ...bei <Thema hier einsetzen> helfen? Jein. Wenn du ehrliches Interesse hast, helfe ich gerne. Was ich allerdings überhaupt nicht abkann ist die "Mach mal"- bzw. "Freibiermentalität", die manche an den Tag legen. Solche "Anfragen" lasse ich liegen. = Kontakt = Solltest du Fragen, Kritik, Verbesserungsvorschläge oder Fehler auf den Seiten hier gefunden haben - eine kleine Mail genügt und wird gerne beantwortet: chris at hobbyelektronik punkt org Wer mich in sozialen Netzwerken sucht, wird wenig erfolg haben. Will ich nicht, mach ich nicht. (siehe auch [[Hobbyelektronik.org:Impressum|Impressum]]) 6cc3b10e7a31477a6f8cc17278007b98e560513a Zeitraffer mit Linux 0 346 947 872 2014-10-03T11:23:08Z Chris 2 Code formatting korrigiert, danke an Sigi wikitext text/x-wiki Was macht man mit einem stromsparenden Computer und einer Webcam? Die Frage habe ich mir genau zur letzten Lernphase meines Studiums gestellt und gleich mal auf die Probe gestellt, ob es möglich ist, innerhalb einer Mittagspause eine Zeitraffer-Kamera zu basteln (siehe auch [http://hobbyelektronik.org/b/2013/06/ein-tag/ hier]). Wenn man als Bash-Anfänger die die Dauer der Mittagspause an die südländische Siesta annähert kann ich schon vorweg sagen: Ja, es ist möglich! = Ausgangsmaterial = Als Computer kommt der Raspberry Pi zum Einsatz. Als Webcam dient eine Logitech C310. Um die SD-Karte etwas zu schonen kommt ein billiger USB-Stick zum Einsatz, der nur als Aufnahmeziel dient. = Einrichten = == Kamera == Da es sich bei der Webcam um eine mit USB-Anschluss handelt, kann sie (meines Wissens) nicht ausschließlich mit dem verwendet werden, das Raspian hergibt. Mit dem Befehl lsusb kann man herausfinden, was am USB hängt: <pre> $ lsusb Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 058f:6387 Alcor Micro Corp. Flash Drive Bus 001 Device 005: ID 046d:081b Logitech, Inc. Webcam C310 </pre> Die Webcam ist also am Computer anhängig, genauso wie der USB-Stick. Über den Befehl ls /dev/video* werden alle Geräte angezeigt, die mit dem Namen video anfangen. Wurden also Treiber für die Kamera gefunden, erscheint sie in der Ausgabe: <pre> $ ls /dev/video* /dev/video0 </pre> Weil cat /dev/video0 > foo.jpg nicht so wirklich funktioniert, muss ein Vermittler her. Ich habe gute Erfahrungen mit fswebcam gemacht. Installation und Test sehen wie folgt aus: <pre> $ sudo apt-get install fswebcam [...] $ fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 testimg.jpg </pre> Der letztere Befehl nimmt ein Bild mit der Auflösung (Parameter -r) 1280x960 auf. Das -q nach der Qualitätsstufe (hier: 85) ist Absicht - bei dem Parameter handelt es sich nicht um -q wie quality, sondern um quiet. Mit -d wird das Device gewählt und anschließend folgt die Ausgabedatei. Diese kann, sofern ein Webserver installiert ist, nach /var/www verschieben oder natürlich direkt auf dem Computer ansehen. In meinem Fall wird der Raspberry "headless" betrieben und die Datei über SSH-Filetransfer auf den Haupt-PC befördert. Funktioniert die Kamera, kann der USB-Speicher angedockt werden: == USB-Stick einbinden == Viele Wege führen bekanntlich nach Rom, genauso kann man Speicher auf verschiedene Weisen einbinden. Das hier ist eine. Zunächst muss ein Verzeichnis angelegt werden, in das der USB-Stick später eingebunden (gemountet) wird. In meinem Fall ist dies /media/usb: <pre> $ sudo mkdir /media/usb </pre> Nun muss herausgefunden werden, wie man den Speicher anspricht. Am besten verwendet man dessen [[wpde:Universally Unique Identifier|Universally Unique Identifier]] (kurz UUID). Der Vorteil an diesem ist, wie der Name schon sagt, dass er Eindeutig ist. Mit dem Befehl blkid können die UUIDs aller verfügbaren Speicher angezeigt werden: <pre> $ sudo blkid /dev/sda1: UUID="0CA5-719C" TYPE="vfat" LABEL="KINGSTON" /dev/mmcblk0p1: SEC_TYPE="msdos" UUID="C522-EA52" TYPE="vfat" /dev/mmcblk0p2: UUID="62ba9ec9-47d9-4421-aaee-71dd6c0f3707" TYPE="ext4" </pre> In geistiger Umnachtung habe ich den USB-Stick "KINGSTON" genannt, das hat allerdings keine Bedeutung. Wichtig ist das, was hinter "UUID=" steht. Man kann den Stick zwar schnell mit mount einbinden, nach dem nächsten Neustart hat man ihn aber verloren und das passiert - auch wenn das System stabil läuft - mit Sicherheit. Also muss er in die fstab (file system table) eingetragen werden. Da man mit ihr nicht spielt, muss sie mit Superuser-Rechten bearbeitet werden: <pre> $ sudo nano /etc/fstab </pre> Die bereits vorhandenen Einträge kann man ignorieren, hier muss der zu verwendende USB-Stick hinzugefügt werden. Ist dieser mit FAT formatiert und hat die UUID 0CA5-719C, kann folgende Zeile an das Ende der Datei geschrieben werden: <pre> UUID=0CA5-719C /media/usb/ vfat defaults,auto,users,noatime,umask=000,rw 0 0 </pre> Mit Strg+X Schließen und das Speichern mit Y und Druck auf die Enter-Taste bestätigen. Navigiert man unter /media/usb kann man nun wunderbar Dateien anlegen, ABER: Diese befinden sich NICHT auf dem USB-Stick! fstab wird nur beim Neustart gelesen. Also heißt es <pre> $ sudo reboot </pre> eingeben und somit die Uptime auf 0 zurücksetzen. Mit dem Befehl df kann jetzt überprüft werden, ob der Speicher richtig eingebunden wurde. Gleichzeitig sieht man auch, wie viel Speicher bereits genutzt wird: <pre> $ df Filesystem 1K-blocks Used Available Use% Mounted on rootfs 1838936 1775400 0 100% / /dev/root 1838936 1775400 0 100% / devtmpfs 110568 0 110568 0% /dev tmpfs 23768 232 23536 1% /run tmpfs 5120 0 5120 0% /run/lock tmpfs 47520 0 47520 0% /run/shm /dev/mmcblk0p1 57288 18960 38328 34% /boot /dev/sda1 4006852 1591764 2415088 40% /media/usb </pre> Der letzte Eintrag ist der interessante: /dev/sda1 ist nach /media/usb gemountet. Wenn man sich nicht sicher ist, kann man vorher von einem anderen PC eine Datei auf dem USB-Stick ablegen und mit ls /media/usb prüfen, ob diese vorhanden ist. (Es kann sein, dass man die Berechtigung auf den Mouting-Point noch anpassen muss, da der Artikels etwas später als das damalige Einrichten entstand, bin ich mir nicht absolut sicher) = Das Zeitraffer-Script = Die Kamera funktioniert, der Zusatzspeicher ist da - nun fehlt nur noch die zeitgesteuerte Aufnahme. Am einfachsten geht das über ein kleines Script, das wahlweise direkt im Benutzerordner (home) angelegt werden kann. Der schnellste Weg nach Hause führt über den Befehl cd. Über den Befehl <pre> $ nano timeshot.sh </pre> wird Nano für die (noch nicht vorhandene) Datei timeshot.sh geöffnet. Dort kann nun folgender Code eingefügt werden: <source lang="bash"> #!/bin/sh dt=$(date +"%Y-%m-%d") time_now=$(date +%s) time_mid=$(date -d "00:00" +%s) mins=$((($time_now-$time_mid)/60)) timestamp=`printf "%04d" $mins` dstdir=/media/usb/timelapse/$dt/ mkdir -p $dstdir fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 $dstdir/img_$timestamp.jpg </source> Ganz oben kommt erst einmal der Shebang, anschließend werden ein paar Variablen definiert: In der Variable dt steht das aktuelle Datum im Format "Jahr-Monat-Datum", anschließend wird in die Variablen time_now und time_mid der Unix-Timestamp (also die Sekunden seit dem 01.01.1970) für die aktuelle Zeit und Mitternacht des aktuellen Tags geschrieben. Anschließend wird die Differenz der beiden Werte berechnet und durch 60 geteilt. Mit dem Befehl `printf "%04d" $mins` wird die Zahl auf alles "vor dem Komma" abgeschnitten und auf 4 Zeichen mit Nullen gefüllt und in die Variable timestamp geschrieben. In timestamp steht also nichts anderes als die aktuelle Minute des Tages. Warum? Später mehr dazu. dstdir gibt, wie sich erahnen lässt, das Zielverzeichnis des Bildes an, wobei der Ordner in der tiefsten Ebene dem aktuellen Datum entspricht. Existiert dieses Verzeichnis nicht, wird es über mkdir angelegt. Im letzten Befehl wird das bereits bekannte Programm fswebcam aufgerufen. Der endgültige Dateiname wird hier noch zusammengebaut. Vor die Minute des Tages wird noch ein "img_" vorangestellt und noch ein ".jpg" angehängt, damit die Dateien auch einen "Nachnamen" haben. Mit Strg+X, y, Enter ist die Datei im Dateisystem, kann aber noch nicht ausgeführt werden. Über den Befehl <pre> $ chmod 766 </pre> gibt man der Datei Ausführungsrechte für den eigenen Benutzer. Führt man sie nun aus, bringt sie zumindest bei mir eine Warnung (die man aber ignorieren kann): <pre> $ ./timeshot.sh Corrupt JPEG data: 1 extraneous bytes before marker 0xd0 </pre> Damit man nun nicht jede Minute vor dem Rechner verbringen muss, ist es zumindest empfehlenswert, die Aufnahme zeitgesteuert auszuführen. Dafür gibt es unter Linux crontab (Zeitplan). Mit dem Befehl crontab -e öffnet man diesen für den aktuellen Benutzer. Ganz am Ende der Datei kann man nun folgendes eintragen: <pre> * * * * * /home/pi/timeshot.sh </pre> Was da auf den ersten Blick etwas kryptisch aussieht ist es eigentlich nicht. /home/pi/timeshot.sh deutet zumindest einmal auf die Datei hin, die ausgeführt wird. Die Sterne vorne sind Wildcards, und bedeutet so viel wie "jede". In Cron gibt man vorne die Ausführung für die Minuten, Stunden, Tage im Monat, den Monaten und Wochentage an. Die 5 Sterne bedeuten also: "Führe die hintenstehende Datei jede Minute, jede Stunde, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Will man in der Nacht keine schwarzen Bilder sammeln, kann man auch folgende Zeile verwenden: <pre> * 6-21 * * * /home/pi/timeshot.sh </pre> Heißt dann so viel wie: "Führe die hintenstehende Datei jede Minute, in den Stunden von 6 bis 21, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Damit ist aber nicht "von 6 bis 21 Uhr!" gemeint - es werden Bilder von 6:00 Uhr bis 21:59 Uhr aufgenommen. = Bilder verarbeiten = Fotos einfach der der Bilder aufnehmen macht natürlich wenig Sinn. Zunächst ist aber erst einmal die Frage: Wie viel Daten kommen überhaupt zusammen? In meinem Fall - jede Minute (also 1440 am Tag) ein Bild 1280x960 bei 85 % Qualität sammeln sich am Tag etwa 85 MiB an. Was macht man damit? Hier ein paar Vorschläge: == Video == Naheliegend ist natürlich, ein Video der Fotos zu erstellen. Nichts leichter als das! Das ist auch der Grund, warum sie nach dem oben angegebenen Schema durchnummeriert sind. Dateien mit diesem Schema lassen sich direkt mit [http://www.ffmpeg.org FFmpeg] verarbeiten. Ich wollte es auf dem Raspberry Pi machen, musste aber sehr schnell einsehen, dass man es schlichtweg vergessen kann, zumindest bei meinen Parametern - h.264 bei 2,5 Mbit/s Bitrate. Die ersten Bilder werden noch relativ schnell zusammengefügt, irgendwann kommt man aber deutlich unter 1 fps beim Codieren. Vermutlich scheitert es hier beim RAM und vermutlich verwendet FFmpeg den in Hardware vorhandenen h.264-Codec nicht. Der Desktop-PC hat da deutlich mehr Power. Also Bilder übertragen, in dem Ordner eine Kommandozeile öffnen und folgenden Befehl reinklöppeln: <pre> ffmpeg.exe -f image2 -i img_%04d.jpg -vcodec libx264 -vb 2500k -acodec null -r 25 day.mp4 </pre> Die Magie kommt vom Parameter -i, in dem alle Bilder mit dem Format img_%04d.jpg zusammengestückelt werden. Wer den Befehl in eine Batch-Datei stecken möchte, muss das % durch %% ersetzen, damit das "%0" nicht interpretiert wird. Allerdings gibt es ein kleines Problem: Fehlt ein Bild, wird die Erstellung dort beendet. Um diesem Problem zu gehen, habe ich ein kleines PHP-Script geschrieben, das hierfür Platzhalter einfügt: <source lang="php"> <?php $w = 1280; $h = 960; $name_min = 0; $name_max = 1439; $name_digits = 4; $name_format = "img_#.jpg"; $im = imagecreatetruecolor($w, $h); $col = imagecolorallocate($im, 0, 0, 255); imagefilledrectangle($im, 0, 0, $w, $h, $col); for($i = $name_min; $i <= $name_max; $i++) { $digits = str_pad($i, $name_digits, "0", STR_PAD_LEFT); $fname = str_replace("#", $digits, $name_format); if(!is_file($fname)) { echo "file " . $fname . " not found - create.\n"; imagejpeg($im, $fname, 85); } } </source> Das Script macht nichts anderes als Dateien mit dem Format "img_#.jpg" zu suchen, wobei # durch eine mit Nullen auf vier aufgefüllten Zahl von 0 bis 1439 ersetzt wird. Ist eine Datei nicht vorhanden, wird für diese das vorbereite Bild als JPEG geschrieben. Wer will, kann anstelle des imagefilledrectangle natürlich jeden anderen Befehl zur Bildmanipulation einsetzen. == Tagesbild == Nicht wirklich aussagekräftig, aber eine nette Spielerei, die im Prinzip ganz einfach ist: Man nimmt von jedem Einzelbild einen von der Uhrzeit abhängigen Streifen heraus und baut damit ein neues Bild, das aus (fast) allen Bildern des Tages zusammengebaut wurde. Da die 1280 Pixel Bildbreite schon relativ nah an den 1400 Bildern pro Tag sind, habe ich vertikale Streifen verwendet. Der Einfachheit halber ist das Script ebenfalls in PHP zusammengeschustert: <source lang="php"> <?php $folder = "/bilder/"; $dst = imagecreatetruecolor(1280, 960); $red = imagecolorallocate($dst, 255, 0, 0); imagefilledrectangle($dst, 0,0,1280,960, $red); for($i = 0; $i < 1280; $i++) { $file = $folder."/img_".str_pad($i+160, 4, "0", STR_PAD_LEFT).".jpg"; if(is_file($file)) { echo "."; $src = imagecreatefromjpeg($file); imagecopyresampled($dst, $src, $i, 0, $i, 0, 1, 1280, 1, 1280); imagedestroy($src); } else { echo "#"; } } echo "\n"; imagejpeg($dst, $folder.".jpg", 90); imagedestroy($dst); </source> Nicht ganz so übersichtlich wie das vorherige Script. Im Prinzip wird für jedes Bild (es wird erst ab Bild 160 eingelesen, damit es 1280 Streifen werden) ein imagecopyresampled in das Zielbild durchgeführt, wobei jeder Streifen 1 Pixel breit ist. Ursprünglich wollte ich jede Streifen 2 bzw. 3 Pixel breit machen und die die "linken" mit leicht überblenden, damit es keine harten Kanten gibt. Nur scheint das in PHP nicht so ganz trivial zu sein. Hier aber ein paar Ergebnisse der Tagesbilder: <gallery> Datei:timelapse_2013-06-14.jpg|14.06.2013 Datei:timelapse_2013-06-17.jpg|17.06.2013 Datei:timelapse_2013-06-21.jpg|21.06.2013 Datei:timelapse_2013-07-01.jpg|01.07.2013 Datei:timelapse_2013-07-09.jpg|09.07.2013 Datei:timelapse_2013-07-19.jpg|19.07.2013 Datei:timelapse_2013-07-23.jpg|23.07.2013 Datei:timelapse_2013-07-31.jpg|31.07.2013 </gallery> == Webserver == Natürlich kann man, wenn man das aktuelle Webcam-Bild auf einer Internetseite einbinden will, jede Minute mit immer gleichem Namen in den /var/www-Ordner kopieren lassen. Normalerweise sollte das Betriebssystem die Datei auch im RAM cachen. Trotzdem kann es sein, dass das Ganze unnütze Schreibzyklen auf dem Flash-Speicher erzeugt und somit für eine schnellere Alterung sorgt. Mit folgendem PHP-Script lässt sich das aktuelle Bild von einem anderen Ort im Dateisystem lesen und in den Webspace holen: <source lang="PHP"> <?php $img_path = "/media/usb/timelapse/#d/img_#m.jpg"; $date = date("Y-m-d"); $minute = date("H") * 60 + date("i"); $search = array("#d", "#m"); $replace = array($date, $minute); $file = str_replace($search, $replace, $img_path); header("Content-Type: Content-Type: image/jpeg"); header("Cache-Control: no-cache, must-revalidate"); if(is_file($file)) { readfile($file); } else { $w = 1280; $h = 960; $im = imagecreatetruecolor($w, $h); $col = imagecolorallocate($im, 0, 0, 255); imagefilledrectangle($im, 0, 0, $w, $h, $col); imagejpeg($im); } </source> Wird kein aktuelles Bild gefunden (entweder weil die Kamera Aufnahmepause hat oder es noch kein Bild gibt - Cron läuft nicht zwangsläufig mit dem Minutenumbruch), wird eine blaue Fläche ausgeliefert. Um die Bilder laden zu können, muss man aber dem Benutzer des Webservers mindestens Leserechte in den entsprechenden Ordnern geben. = Anmerkungen = Hier noch ein paar Dinge, die mir beim Betreiben der Kamera aufgefallen sind: * Auch halbwegs moderne Bildsensoren [http://hobbyelektronik.org/b/2013/06/ein-tag/ mögen keine dauerhafte Sonneneinstrahlung] * <strike>Die Logitech-Kamera oder deren Treiber stürzen ab und zu ab und reißen den kompletten Raspberry Pi herunter.</strike> * Schuld ist wohl die [http://hobbyelektronik.org/b/2013/12/warum-der-pi-abschmiert/ Netzwerkkarte]. sudo rpi-update hilft, löst das Problem aber nicht vollständig. [[Kategorie:Software]] [[Kategorie:Linux]] [[Kategorie:Raspberry Pi]] b5d438ce15e0cc3043e3c3763b8bf86932b9637f Datei:StellarisToolchainMakefile.h 6 387 949 2014-11-10T20:19:14Z Jan 4 Makefile zum Bauen der Stellaris Launchpad Toolchain wikitext text/x-wiki Makefile zum Bauen der Stellaris Launchpad Toolchain bf57e3b752e5a2adf2b14deece18e56d77d2d5f4 Stellaris Launchpad-Toolchain unter Linux 0 388 950 2014-11-10T20:29:05Z Jan 4 Die Seite wurde neu angelegt: „=Einleitende Worte= Im folgenden wird beschrieben, wie man sich die Toolchain, Debugger und Flashtools zum Programmieren via USB für das Stellaris Launchpad v…“ wikitext text/x-wiki =Einleitende Worte= Im folgenden wird beschrieben, wie man sich die Toolchain, Debugger und Flashtools zum Programmieren via USB für das Stellaris Launchpad von Grund auf selber baut. Die Idee dazu kam mir, als ich Probleme mit einem der 32bit Compiler von Ti unter einem 64bit Betriebssystem hatten. Außerdem ist es natürlich deutlich "cooler" seine eigenen Compiler zu verwenden! So kann man bei Problemen auch einfach mal im Source Code stöbern. An dieser Stelle sei gesagt, das dieser Vorgang sehr rechen- und zeitintensiv ist und ihr während des Bauvorgangs deutlich über 10 Tassen Kaffe trinken könnt. Um Missverständnisse auszuräumen, sei kurz erwähnt, dass dieses Tutorial für Linuxanwender gedacht ist und eine Portierung auf Windos schwer sein dürfe. Die komplette Software für die Toolchain kann mittels eines Makefiles([[Datei:StellarisToolchainMakefile.h]]) heruntergeladen und gebaut werden. Am Anfang des Artikels wird die Verwendung dieses Makefiles erklärt. Danach wird auf die einzelen Kompontenen kurz eingegangen. <b>Warnung:</b> Die hier verwendeten Softwarepackete unterliegen verschiedensten Lizenzen, welche eingehalten müssen werden! =Howto= Zu Begin sollte man sich das Makefile herrunterladen und in einem beliebigen Ordner speichern: <pre> $ mkdir ~/stellarislaunchpad/ $ wget http://hobbyelektronik.org/w/images/d/d6/StellarisToolchainMakefile.h -O ~/stellarislaunchpad/Makefile </pre> Anschließend folgt das herrunterladen aller Sourcen. Diese haben entpackt eine Größe von ca. 1.4Gb und liegen in dem Ordner "~/stellarislaunchpad/source". Zur Überprüfung sind hier die herruntergeladen Packete aufgeführt. <pre> $ make initial -C ~/stellarislaunchpad/ ...... $ ls -1 ~/stellarislaunchpad/source/ binutils-2.22 gcc-4.9.0 gdb-7.8 lm4tools-master newlib-2.1.0 openocd-0.8.0 stellarisWare-master texinfo-5.2 </pre> Jetzt kann der eigentliche Bauvorgang gestartet werden. Dieser wird je nach Rechenleistung des Computers mehrere Stunden benötigen. Die Anzahl der Jobs, mit denen gebaut wird, berechnet sich automatisch aus der Anzahl der Prozessoren. Daher das "make" nicht mit mehren Jobs zu starten! <pre> $ make all -C ~/stellarislaunchpad/ </pre> Das Ergebnis des Bauvorgangs mit Compiler, Gdb, lm4flash, usw. befindet sich in dem Ordner ~/stellarislaunchpad/. Hier die wichtigsten Binarys: <pre> ~/stellarislaunchpad/output/bin/arm-none-eabi-gcc # c compiler ~/stellarislaunchpad/output/bin/lm4flash # tool to programm the stellaris launchpad via usb ~/stellarislaunchpad/output/bin/arm-none-eabi-gdb # gdb ~/stellarislaunchpad/output/arm-none-eabi/sys-include/ # folder with usefull header </pre> Nach diesem langwierigem Prozess des Bauens können wir uns endlich der Programmierung des Stellaris Launchpads widmen. Hierfür ist in dem Makefile ein Beispiel vorhanden. Dabei wird das "blinky" Projekt der Stellaris Ware gebaut und auf das Lauchpad gespielt. Dazu muss das Launchpad selbstverständlich am Pc via USB eingesteckt sein. Leider ist es mir bis jetzt nicht gelungen, das lm4flash Tool ohne Rootrechte zu starten. Der Systemcall dazu lautet: <pre> $ sudo make example -C ~/stellarislaunchpad/ </pre> Ist alles gut gegangen, blinkt das Stellaris Launchpad nun fröhlich in grün vor sich hin. Bei der Stellaris Ware (unter ~/stellarisware/source/stellarisWare-master/) befinden sich noch viele weitere Beispiele, welche zum experimentieren einladen. =Erklärung des Makefiles= IN BEARBEITUNG! [[Kategorie:Software]] 8764b69a8fd4f6af69b9fb663eaac2287c0efa79 951 950 2014-11-10T20:33:55Z Jan 4 wikitext text/x-wiki =Einleitende Worte= Im folgenden wird beschrieben, wie man sich die Toolchain, Debugger und Flashtools zum Programmieren via USB für das Stellaris Launchpad von Grund auf selber baut. Die Idee dazu kam mir, als ich Probleme mit einem der 32bit Compiler von Ti unter einem 64bit Betriebssystem hatten. Außerdem ist es natürlich deutlich "cooler" seine eigenen Compiler zu verwenden! So kann man bei Problemen auch einfach mal im Source Code stöbern. An dieser Stelle sei gesagt, das dieser Vorgang sehr rechen- und zeitintensiv ist und ihr während des Bauvorgangs deutlich über 10 Tassen Kaffe trinken könnt. Um Missverständnisse auszuräumen, sei kurz erwähnt, dass dieses Tutorial für Linuxanwender gedacht ist und eine Portierung auf Windos schwer sein dürfe. Die komplette Software für die Toolchain kann mittels eines Makefiles([[Datei:StellarisToolchainMakefile.h]]) heruntergeladen und gebaut werden. Am Anfang des Artikels wird die Verwendung dieses Makefiles erklärt. Danach wird auf die einzelen Kompontenen kurz eingegangen. <b>Warnung:</b> Die hier verwendeten Softwarepackete unterliegen verschiedensten Lizenzen, welche eingehalten müssen werden! =Howto build Toolchain= Zu Begin sollte man sich das Makefile herrunterladen und in einem beliebigen Ordner speichern: <pre> $ mkdir ~/stellarislaunchpad/ $ wget http://hobbyelektronik.org/w/images/d/d6/StellarisToolchainMakefile.h -O ~/stellarislaunchpad/Makefile </pre> Anschließend folgt das herrunterladen aller Sourcen. Diese haben entpackt eine Größe von ca. 1.4Gb und liegen in dem Ordner "~/stellarislaunchpad/source". Zur Überprüfung sind hier die herruntergeladen Packete aufgeführt. <pre> $ make initial -C ~/stellarislaunchpad/ ...... $ ls -1 ~/stellarislaunchpad/source/ binutils-2.22 gcc-4.9.0 gdb-7.8 lm4tools-master newlib-2.1.0 openocd-0.8.0 stellarisWare-master texinfo-5.2 </pre> Jetzt kann der eigentliche Bauvorgang gestartet werden. Dieser wird je nach Rechenleistung des Computers mehrere Stunden benötigen. Die Anzahl der Jobs, mit denen gebaut wird, berechnet sich automatisch aus der Anzahl der Prozessoren. Daher das "make" nicht mit mehren Jobs zu starten! <pre> $ make all -C ~/stellarislaunchpad/ </pre> Das Ergebnis des Bauvorgangs mit Compiler, Gdb, lm4flash, usw. befindet sich in dem Ordner ~/stellarislaunchpad/. Hier die wichtigsten Binarys: <pre> ~/stellarislaunchpad/output/bin/arm-none-eabi-gcc # c compiler ~/stellarislaunchpad/output/bin/lm4flash # tool to programm the stellaris launchpad via usb ~/stellarislaunchpad/output/bin/arm-none-eabi-gdb # gdb ~/stellarislaunchpad/output/arm-none-eabi/sys-include/ # folder with usefull header </pre> Nach diesem langwierigem Prozess des Bauens können wir uns endlich der Programmierung des Stellaris Launchpads widmen. Hierfür ist in dem Makefile ein Beispiel vorhanden. Dabei wird das "blinky" Projekt der Stellaris Ware gebaut und auf das Lauchpad gespielt. Dazu muss das Launchpad selbstverständlich am Pc via USB eingesteckt sein. Leider ist es mir bis jetzt nicht gelungen, das lm4flash Tool ohne Rootrechte zu starten. Der Systemcall dazu lautet: <pre> $ sudo make example -C ~/stellarislaunchpad/ </pre> Ist alles gut gegangen, blinkt das Stellaris Launchpad nun fröhlich in grün vor sich hin. Bei der Stellaris Ware (unter ~/stellarisware/source/stellarisWare-master/) befinden sich noch viele weitere Beispiele, welche zum experimentieren einladen. =Erklärung des Makefiles= IN BEARBEITUNG! [[Kategorie:Software]] a3ec80bc23b02bcc12b1c5ffa9c3e0bf8febd164 952 951 2014-11-10T20:54:54Z Chris 2 Spellcheck wikitext text/x-wiki Im folgenden wird beschrieben, wie man sich die Toolchain, Debugger und Flashtools zum Programmieren via USB für das Stellaris Launchpad von Grund auf selber baut. Die Idee dazu kam mir, als ich Probleme mit einem der 32bit Compiler von TI unter einem 64bit Betriebssystem hatten. Außerdem ist es natürlich deutlich "cooler" seine eigenen Compiler zu verwenden! So kann man bei Problemen auch einfach mal im Source Code stöbern. An dieser Stelle sei gesagt, das dieser Vorgang sehr rechen- und zeitintensiv ist und ihr während des Bauvorgangs deutlich über 10 Tassen Kaffee trinken könnt. Um Missverständnisse auszuräumen, sei kurz erwähnt, dass dieses Tutorial für Linuxanwender gedacht ist und eine Portierung auf Windos schwer sein dürfe. Die komplette Software für die Toolchain kann mittels eines Makefiles([[Datei:StellarisToolchainMakefile.h]]) heruntergeladen und gebaut werden. Am Anfang des Artikels wird die Verwendung dieses Makefiles erklärt. Danach wird auf die einzelnen Komponenten kurz eingegangen. <b>Warnung:</b> Die hier verwendeten Softwarepakete unterliegen verschiedensten Lizenzen, welche eingehalten müssen werden! =Bauen der Toolchain= Zu Begin sollte man sich das Makefile herunterladen und in einem beliebigen Ordner speichern: <pre> $ mkdir ~/stellarislaunchpad/ $ wget http://hobbyelektronik.org/w/images/d/d6/StellarisToolchainMakefile.h -O ~/stellarislaunchpad/Makefile </pre> Anschließend folgt das Herunterladen aller Sourcen. Diese haben entpackt eine Größe von ca. 1.4 GiB und liegen in dem Ordner "~/stellarislaunchpad/source". Zur Überprüfung sind hier die heruntergeladen Pakete aufgeführt. <pre> $ make initial -C ~/stellarislaunchpad/ ...... $ ls -1 ~/stellarislaunchpad/source/ binutils-2.22 gcc-4.9.0 gdb-7.8 lm4tools-master newlib-2.1.0 openocd-0.8.0 stellarisWare-master texinfo-5.2 </pre> Jetzt kann der eigentliche Bauvorgang gestartet werden. Dieser wird je nach Rechenleistung des Computers mehrere Stunden benötigen. Die Anzahl der Jobs, mit denen gebaut wird, berechnet sich automatisch aus der Anzahl der Prozessoren. Daher das "make" nicht mit mehren Jobs starten! <pre> $ make all -C ~/stellarislaunchpad/ </pre> Das Ergebnis des Bauvorgangs mit Compiler, Gdb, lm4flash, usw. befindet sich in dem Ordner ~/stellarislaunchpad/. Die wichtigsten Binaries sind: <pre> ~/stellarislaunchpad/output/bin/arm-none-eabi-gcc # c compiler ~/stellarislaunchpad/output/bin/lm4flash # tool to programm the stellaris launchpad via usb ~/stellarislaunchpad/output/bin/arm-none-eabi-gdb # gdb ~/stellarislaunchpad/output/arm-none-eabi/sys-include/ # folder with usefull header </pre> Nach diesem langwierigem Prozess des Bauens können wir uns endlich der Programmierung des Stellaris Launchpads widmen. Hierfür ist in dem Makefile ein Beispiel vorhanden. Dabei wird das "blinky" Projekt der Stellaris Ware gebaut und auf das Lauchpad gespielt. Dazu muss das Launchpad selbstverständlich am PC via USB eingesteckt sein. Leider ist es mir bis jetzt nicht gelungen, das lm4flash Tool ohne Rootrechte zu starten. Der Systemcall dazu lautet: <pre> $ sudo make example -C ~/stellarislaunchpad/ </pre> Ist alles gut gegangen, blinkt das Stellaris Launchpad nun fröhlich in grün vor sich hin. Bei der Stellaris Ware (unter ~/stellarisware/source/stellarisWare-master/) befinden sich noch viele weitere Beispiele, welche zum experimentieren einladen. =Erklärung des Makefiles= IN BEARBEITUNG! [[Kategorie:Software]] 04b0b5a32671e077511e526fa931a0a37ca3f947 953 952 2014-11-10T21:04:33Z Chris 2 verschob „[[Stellaris Launchpad]]“ nach „[[Stellaris Launchpad-Toolchain unter Linux]]“ wikitext text/x-wiki Im folgenden wird beschrieben, wie man sich die Toolchain, Debugger und Flashtools zum Programmieren via USB für das Stellaris Launchpad von Grund auf selber baut. Die Idee dazu kam mir, als ich Probleme mit einem der 32bit Compiler von TI unter einem 64bit Betriebssystem hatten. Außerdem ist es natürlich deutlich "cooler" seine eigenen Compiler zu verwenden! So kann man bei Problemen auch einfach mal im Source Code stöbern. An dieser Stelle sei gesagt, das dieser Vorgang sehr rechen- und zeitintensiv ist und ihr während des Bauvorgangs deutlich über 10 Tassen Kaffee trinken könnt. Um Missverständnisse auszuräumen, sei kurz erwähnt, dass dieses Tutorial für Linuxanwender gedacht ist und eine Portierung auf Windos schwer sein dürfe. Die komplette Software für die Toolchain kann mittels eines Makefiles([[Datei:StellarisToolchainMakefile.h]]) heruntergeladen und gebaut werden. Am Anfang des Artikels wird die Verwendung dieses Makefiles erklärt. Danach wird auf die einzelnen Komponenten kurz eingegangen. <b>Warnung:</b> Die hier verwendeten Softwarepakete unterliegen verschiedensten Lizenzen, welche eingehalten müssen werden! =Bauen der Toolchain= Zu Begin sollte man sich das Makefile herunterladen und in einem beliebigen Ordner speichern: <pre> $ mkdir ~/stellarislaunchpad/ $ wget http://hobbyelektronik.org/w/images/d/d6/StellarisToolchainMakefile.h -O ~/stellarislaunchpad/Makefile </pre> Anschließend folgt das Herunterladen aller Sourcen. Diese haben entpackt eine Größe von ca. 1.4 GiB und liegen in dem Ordner "~/stellarislaunchpad/source". Zur Überprüfung sind hier die heruntergeladen Pakete aufgeführt. <pre> $ make initial -C ~/stellarislaunchpad/ ...... $ ls -1 ~/stellarislaunchpad/source/ binutils-2.22 gcc-4.9.0 gdb-7.8 lm4tools-master newlib-2.1.0 openocd-0.8.0 stellarisWare-master texinfo-5.2 </pre> Jetzt kann der eigentliche Bauvorgang gestartet werden. Dieser wird je nach Rechenleistung des Computers mehrere Stunden benötigen. Die Anzahl der Jobs, mit denen gebaut wird, berechnet sich automatisch aus der Anzahl der Prozessoren. Daher das "make" nicht mit mehren Jobs starten! <pre> $ make all -C ~/stellarislaunchpad/ </pre> Das Ergebnis des Bauvorgangs mit Compiler, Gdb, lm4flash, usw. befindet sich in dem Ordner ~/stellarislaunchpad/. Die wichtigsten Binaries sind: <pre> ~/stellarislaunchpad/output/bin/arm-none-eabi-gcc # c compiler ~/stellarislaunchpad/output/bin/lm4flash # tool to programm the stellaris launchpad via usb ~/stellarislaunchpad/output/bin/arm-none-eabi-gdb # gdb ~/stellarislaunchpad/output/arm-none-eabi/sys-include/ # folder with usefull header </pre> Nach diesem langwierigem Prozess des Bauens können wir uns endlich der Programmierung des Stellaris Launchpads widmen. Hierfür ist in dem Makefile ein Beispiel vorhanden. Dabei wird das "blinky" Projekt der Stellaris Ware gebaut und auf das Lauchpad gespielt. Dazu muss das Launchpad selbstverständlich am PC via USB eingesteckt sein. Leider ist es mir bis jetzt nicht gelungen, das lm4flash Tool ohne Rootrechte zu starten. Der Systemcall dazu lautet: <pre> $ sudo make example -C ~/stellarislaunchpad/ </pre> Ist alles gut gegangen, blinkt das Stellaris Launchpad nun fröhlich in grün vor sich hin. Bei der Stellaris Ware (unter ~/stellarisware/source/stellarisWare-master/) befinden sich noch viele weitere Beispiele, welche zum experimentieren einladen. =Erklärung des Makefiles= IN BEARBEITUNG! [[Kategorie:Software]] 04b0b5a32671e077511e526fa931a0a37ca3f947 955 953 2014-11-10T21:15:16Z Chris 2 nochmal Typojagd wikitext text/x-wiki Im folgenden wird beschrieben, wie man sich die Toolchain, Debugger und Flashtools zum Programmieren via USB für das Stellaris Launchpad von Grund auf selber baut. Die Idee dazu kam mir, als ich Probleme mit einem der 32bit Compiler von TI unter einem 64bit Betriebssystem hatten. Außerdem ist es natürlich deutlich "cooler", seine eigenen Compiler zu verwenden! So kann man bei Problemen auch einfach mal im Source Code stöbern. An dieser Stelle sei gesagt, das dieser Vorgang sehr rechen- und zeitintensiv ist und ihr während des Bauvorgangs deutlich über 10 Tassen Kaffee trinken könnt. Um Missverständnisse auszuräumen sei kurz erwähnt, dass dieses Tutorial für Linuxanwender gedacht ist und eine Portierung auf Windows schwer sein dürfe. Die komplette Software für die Toolchain kann mittels eines Makefiles ([[Datei:StellarisToolchainMakefile.h]]) heruntergeladen und gebaut werden. Am Anfang des Artikels wird die Verwendung dieses Makefiles erklärt. Danach wird auf die einzelnen Komponenten kurz eingegangen. <b>Warnung:</b> Die hier verwendeten Softwarepakete unterliegen verschiedensten Lizenzen, welche eingehalten müssen werden! =Bauen der Toolchain= Zu Beginn sollte man sich das Makefile herunterladen und in einem beliebigen Ordner speichern: <pre> $ mkdir ~/stellarislaunchpad/ $ wget http://hobbyelektronik.org/w/images/d/d6/StellarisToolchainMakefile.h -O ~/stellarislaunchpad/Makefile </pre> Anschließend folgt das Herunterladen aller Sourcen. Diese haben entpackt eine Größe von ca. 1.4 GiB und liegen in dem Ordner "~/stellarislaunchpad/source". Zur Überprüfung sind hier die heruntergeladen Pakete aufgeführt. <pre> $ make initial -C ~/stellarislaunchpad/ ...... $ ls -1 ~/stellarislaunchpad/source/ binutils-2.22 gcc-4.9.0 gdb-7.8 lm4tools-master newlib-2.1.0 openocd-0.8.0 stellarisWare-master texinfo-5.2 </pre> Jetzt kann der eigentliche Bauvorgang gestartet werden. Dieser wird je nach Rechenleistung des Computers mehrere Stunden benötigen. Die Anzahl der Jobs, mit denen gebaut wird, berechnet sich automatisch aus der Anzahl der Prozessoren. Daher das "make" nicht mit mehreren Jobs starten! <pre> $ make all -C ~/stellarislaunchpad/ </pre> Das Ergebnis des Bauvorgangs mit Compiler, Gdb, lm4flash, usw. befindet sich in dem Ordner ~/stellarislaunchpad/. Die wichtigsten Binaries sind: <pre> ~/stellarislaunchpad/output/bin/arm-none-eabi-gcc # c compiler ~/stellarislaunchpad/output/bin/lm4flash # tool to programm the stellaris launchpad via usb ~/stellarislaunchpad/output/bin/arm-none-eabi-gdb # gdb ~/stellarislaunchpad/output/arm-none-eabi/sys-include/ # folder with useful header </pre> Nach diesem langwierigem Prozess des Bauens können wir uns endlich der Programmierung des Stellaris Launchpads widmen. Hierfür ist in dem Makefile ein Beispiel vorhanden. Dabei wird das "blinky" Projekt der Stellaris Ware gebaut und auf das Lauchpad gespielt. Dazu muss das Launchpad selbstverständlich am PC via USB eingesteckt sein. Leider ist es mir bis jetzt nicht gelungen, das lm4flash Tool ohne Rootrechte zu starten. Der Systemcall dazu lautet: <pre> $ sudo make example -C ~/stellarislaunchpad/ </pre> Ist alles gut gegangen, blinkt das Stellaris Launchpad nun fröhlich in grün vor sich hin. Bei der Stellaris Ware (unter ~/stellarisware/source/stellarisWare-master/) befinden sich noch viele weitere Beispiele, welche zum experimentieren einladen. =Erklärung des Makefiles= IN BEARBEITUNG! [[Kategorie:Software]] 7fedfe569912e7d071766dddbf27436c53b5c67d 956 955 2014-11-18T18:37:39Z Jan 4 /* Erklärung des Makefiles */ wikitext text/x-wiki Im folgenden wird beschrieben, wie man sich die Toolchain, Debugger und Flashtools zum Programmieren via USB für das Stellaris Launchpad von Grund auf selber baut. Die Idee dazu kam mir, als ich Probleme mit einem der 32bit Compiler von TI unter einem 64bit Betriebssystem hatten. Außerdem ist es natürlich deutlich "cooler", seine eigenen Compiler zu verwenden! So kann man bei Problemen auch einfach mal im Source Code stöbern. An dieser Stelle sei gesagt, das dieser Vorgang sehr rechen- und zeitintensiv ist und ihr während des Bauvorgangs deutlich über 10 Tassen Kaffee trinken könnt. Um Missverständnisse auszuräumen sei kurz erwähnt, dass dieses Tutorial für Linuxanwender gedacht ist und eine Portierung auf Windows schwer sein dürfe. Die komplette Software für die Toolchain kann mittels eines Makefiles ([[Datei:StellarisToolchainMakefile.h]]) heruntergeladen und gebaut werden. Am Anfang des Artikels wird die Verwendung dieses Makefiles erklärt. Danach wird auf die einzelnen Komponenten kurz eingegangen. <b>Warnung:</b> Die hier verwendeten Softwarepakete unterliegen verschiedensten Lizenzen, welche eingehalten müssen werden! =Bauen der Toolchain= Zu Beginn sollte man sich das Makefile herunterladen und in einem beliebigen Ordner speichern: <pre> $ mkdir ~/stellarislaunchpad/ $ wget http://hobbyelektronik.org/w/images/d/d6/StellarisToolchainMakefile.h -O ~/stellarislaunchpad/Makefile </pre> Anschließend folgt das Herunterladen aller Sourcen. Diese haben entpackt eine Größe von ca. 1.4 GiB und liegen in dem Ordner "~/stellarislaunchpad/source". Zur Überprüfung sind hier die heruntergeladen Pakete aufgeführt. <pre> $ make initial -C ~/stellarislaunchpad/ ...... $ ls -1 ~/stellarislaunchpad/source/ binutils-2.22 gcc-4.9.0 gdb-7.8 lm4tools-master newlib-2.1.0 openocd-0.8.0 stellarisWare-master texinfo-5.2 </pre> Jetzt kann der eigentliche Bauvorgang gestartet werden. Dieser wird je nach Rechenleistung des Computers mehrere Stunden benötigen. Die Anzahl der Jobs, mit denen gebaut wird, berechnet sich automatisch aus der Anzahl der Prozessoren. Daher das "make" nicht mit mehreren Jobs starten! <pre> $ make all -C ~/stellarislaunchpad/ </pre> Das Ergebnis des Bauvorgangs mit Compiler, Gdb, lm4flash, usw. befindet sich in dem Ordner ~/stellarislaunchpad/. Die wichtigsten Binaries sind: <pre> ~/stellarislaunchpad/output/bin/arm-none-eabi-gcc # c compiler ~/stellarislaunchpad/output/bin/lm4flash # tool to programm the stellaris launchpad via usb ~/stellarislaunchpad/output/bin/arm-none-eabi-gdb # gdb ~/stellarislaunchpad/output/arm-none-eabi/sys-include/ # folder with useful header </pre> Nach diesem langwierigem Prozess des Bauens können wir uns endlich der Programmierung des Stellaris Launchpads widmen. Hierfür ist in dem Makefile ein Beispiel vorhanden. Dabei wird das "blinky" Projekt der Stellaris Ware gebaut und auf das Lauchpad gespielt. Dazu muss das Launchpad selbstverständlich am PC via USB eingesteckt sein. Leider ist es mir bis jetzt nicht gelungen, das lm4flash Tool ohne Rootrechte zu starten. Der Systemcall dazu lautet: <pre> $ sudo make example -C ~/stellarislaunchpad/ </pre> Ist alles gut gegangen, blinkt das Stellaris Launchpad nun fröhlich in grün vor sich hin. Bei der Stellaris Ware (unter ~/stellarisware/source/stellarisWare-master/) befinden sich noch viele weitere Beispiele, welche zum experimentieren einladen. =Erklärung des Makefiles= Im folgenden wird genauer auf die einzelnen Teile des Makefiles eingegangen. ==Verwendete Variablen== Die wichtigsten globalen Variablen des Makefiles werden hier kurz genannt. Nicht aufgeführt sind die Variablen für den Speicherort und Version der einzelnen Pakete. <pre> BASE = $(shell pwd) # the act. folder PREFIX = $(BASE)/output # install folder SOURCE = $(BASE)/source/ # source folder TARGET = arm-none-eabi # target name JOBS = $(shell cat /proc/cpuinfo | grep MHz | wc -l) # number of jobs for make MAKE = PATH=$(PREFIX)/bin:$${PATH} make -j $(JOBS) # make variable with modified path and the number of jobs </pre> ==Texinfo== Texinfo beinhaltet das Programm "makeinfo", welches beim Bauvorgang der Newlib benötigt wird. Nur aus diesem Grund wird dieses relativ kleine Software-Paket mit gebaut. <pre> texinfo: cd $(TEXINFO_DIR) && ./configure \ --prefix=$(PREFIX) $(MAKE) -C $(TEXINFO_DIR) all $(MAKE) -C $(TEXINFO_DIR) install </pre> ==Binutils== Die Binutils beinhalten eine Vielzahl an Werkzeugen, unter anderem zum übersetzen von Code. Mehr Informationen dazu gibt es auf der GNU-Website. <pre> binutils: cd $(BINUTILS_DIR) && ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --disable-nls \ --enable-multilib \ --with-gnu-as \ --with-gnu-ld \ --disable-libssp \ --disable-werror $(MAKE) -C $(BINUTILS_DIR) all $(MAKE) -C $(BINUTILS_DIR) install </pre> ==Gcc-initial== Nun wird der eigentliche Gcc Compiler gebaut. Dieser benötigt zum vollständigen Bauen eine Library mit grundlegenden Funktionen und den entsprechenden Header Dateien. Nachdem die glibc Library zu groß für Mikrocontroller ist, bietet sich Newlib an. Zum Bauen der Newlib muss allerdings ein Teil des Gcc bereits vorhanden sein, weshalb der Gcc in zwei Schritten gebaut wird. Hier die richtige Reihenfolge: # GCC-Configure # GCC-make all-gcc # GCC-make install-gcc # NEWLIB-configure # NEWLIB-make # NEWLIB-make install # GCC-make all # GCC-make install Erst nach dem erfolgreichen "make install" vom Gcc ist dieser komplett gebaut. Aber nun zu der Erklärung. Zu Beginn wird im Gcc-Verzeichnis ein neuer Ordner angelegt, weil man den Gcc nicht direkt in dem Verzeichnis der Sourcen bauen kann. Bei der Konfiguration werden eine Vielzahl an Features ausgeschaltet, welche auf dem Mikrocontroller nicht benötigt werden. Wichtig ist das setzen des "--enable-languages" Flag für die gewünschte Sprache. Dazu kommt natürlich das entsprechende Flag für die Newlib("--with-newlib"). Um diese zu verwenden, muss der Headerpfad zu der Newlib entsprechend angegeben werden("--with-headers"). Zudem ist auch die Angabe des CPU-Typs(cortex-m4) wichtig. <pre> gcc-initial: mkdir -p $(GCC_DIR)/build cd $(GCC_DIR)/build && PATH=$(PREFIX)/bin:$${PATH} ../configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-languages=c \ --disable-bootstrap \ --disable-libgomp \ --disable-libmudflap \ --enable-multilib \ --disable-libphobos \ --disable-decimal-float \ --disable-libffi \ --disable-libmudflap \ --disable-libquadmath \ --disable-libssp \ --disable-libstdcxx-pch \ --disable-nls \ --disable-shared \ --disable-threads \ --disable-tls \ --with-gnu-as \ --with-gnu-ld \ --with-cpu=cortex-m4 \ --with-tune=cortex-m4 \ --with-mode=thumb \ --with-newlib \ --with-headers=$(NEWLIB_DIR)/newlib/libc/include/ $(MAKE) -C $(GCC_DIR)/build/ all-gcc $(MAKE) -C $(GCC_DIR)/build/ install-gcc </pre> ==Newlib== Vor dem Bauen der Newlib muss die verwendete Version 2.1.0 noch gepatcht werden, weil es sonst zu Komplikationen beim bauen kommt. Der Patch ist in das Makefile integriert und wird sofort nach Herunterladen der Sourcen eingespielt. Hier der Patch: <pre> --- libgloss/arm/cpu-init/Makefile.in 2013-10-14 17:15:12.000000000 +0200 +++ libgloss/arm/cpu-init/Makefile.in 2014-10-17 21:38:32.623317260 +0200 @@ -18,6 +18,7 @@ tooldir = $(exec_prefix)/$(target_alias) objtype = @objtype@ +host_makefile_frag = /../../config/default.mh INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -80,7 +81,7 @@ install-info: clean-info: -Makefile: Makefile.in ../config.status @host_makefile_frag_path@ +Makefile: Makefile.in ../config.status $${host_makefile_frag_path} $$(SHELL) ../config.status --file cpu-init/Makefile ../config.status: ../configure </pre> Zum Konfigurieren der Newlib gibt es nichts besonders zu erwähnen. Es wird wie beim Gcc natürlich auch unser Target angegeben. Wichtig ist beim installieren, dass hier nicht unsere "$(MAKE)" Variable verwendet wird. Da es sonst beim Verwenden mehrerer Jobs zu Problemen führen kann. <pre> newlib: cd $(NEWLIB_DIR) && PATH=$${PATH}/:$(PREFIX)/bin/ ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-multilib \ --disable-libssp \ --disable-nls $(MAKE) -C $(NEWLIB_DIR) all # use normal make without jobs because of issues with multiple jobs PATH=$(PREFIX)/bin:$${PATH} make -C $(NEWLIB_DIR) install </pre> ==Gcc-final== Endlich ist es so weit. Wir können unseren Compiler fertig bauen und installieren. Der Compiler befindet sich anschließend unter output/bin/arm-none-eabi-gcc und kann nun verwendet werden. <pre> gcc-final: $(MAKE) -C $(GCC_DIR)/build/ all $(MAKE) -C $(GCC_DIR)/build/ install </pre> ==Lm4flash== Zum Aufspielen der Software auf das Launchpad benötigt man die Lm4flash-tools. Diese brauchen zwingend das Paket libusb und das dazugehörige Developer Package. Unter Arch und Ubuntu können diese leicht über die Paketmanager installiert werden. <pre> lm4tools: echo "lm4tools needs libusb dev and pkg(try apt-get install libusb-dev)" make -C $(LM4TOOLS_DIR)/lm4flash cp $(LM4TOOLS_DIR)/lm4flash/lm4flash $(PREFIX)/bin/ </pre> Getestet werden kann Lm4flash einfach mit dem flash-blinky Beispiel des Makefiles. Dazu wird das blinky-Projekt der Stellarisware crosscompiliert und per lm4flash auf das Launchpad via USB gespielt. Möglicherweise wird zum Übertragen der Daten Rootrechte benötigt. <pre> blinky: $(MAKE) -C $(STELLARISWARE_DIR)/boards/ek-lm4f120xl/blinky/ flash-blinky: blinky $(PREFIX)/bin/lm4flash $(STELLARISWARE_DIR)/boards/ek-lm4f120xl/blinky/gcc/blinky.bin </pre> ==GDB== Zum Debuggen wird nun noch der entsprechende Gdb benötigt. Auch dieser kann ohne große Mühe gebaut werden. Hier wird nicht weiter auf den Gdb eingegangen, da es genügend ausführliche Anleitungen im Internet gibt. <pre> gdb: cd $(GDB_DIR) && ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-interwork \ --enable-multilib $(MAKE) -C $(GDB_DIR) all $(MAKE) -C $(GDB_DIR) install </pre> ==OpenOCD== Und für alle Freunde von OpenOCD wird der nötige Bauvorgang kurz gezeigt. Wichtig dabei ist das "--enable-ti-icdi" Flag. <pre> openocd: cd $(OPENOCD_DIR) && ./configure \ --prefix=$(PREFIX) \ --enable-maintainer-mode \ --enable-ti-icdi $(MAKE) -C $(OPENOCD_DIR) all $(MAKE) -C $(OPENOCD_DIR) install </pre> [[Kategorie:Software]] 0d1d161a1f04f6ab1328f879fbd3df445e67aa5f 957 956 2014-11-18T19:27:55Z Jan 4 /* Newlib */ Fehlerausgabe hinzugefügt wikitext text/x-wiki Im folgenden wird beschrieben, wie man sich die Toolchain, Debugger und Flashtools zum Programmieren via USB für das Stellaris Launchpad von Grund auf selber baut. Die Idee dazu kam mir, als ich Probleme mit einem der 32bit Compiler von TI unter einem 64bit Betriebssystem hatten. Außerdem ist es natürlich deutlich "cooler", seine eigenen Compiler zu verwenden! So kann man bei Problemen auch einfach mal im Source Code stöbern. An dieser Stelle sei gesagt, das dieser Vorgang sehr rechen- und zeitintensiv ist und ihr während des Bauvorgangs deutlich über 10 Tassen Kaffee trinken könnt. Um Missverständnisse auszuräumen sei kurz erwähnt, dass dieses Tutorial für Linuxanwender gedacht ist und eine Portierung auf Windows schwer sein dürfe. Die komplette Software für die Toolchain kann mittels eines Makefiles ([[Datei:StellarisToolchainMakefile.h]]) heruntergeladen und gebaut werden. Am Anfang des Artikels wird die Verwendung dieses Makefiles erklärt. Danach wird auf die einzelnen Komponenten kurz eingegangen. <b>Warnung:</b> Die hier verwendeten Softwarepakete unterliegen verschiedensten Lizenzen, welche eingehalten müssen werden! =Bauen der Toolchain= Zu Beginn sollte man sich das Makefile herunterladen und in einem beliebigen Ordner speichern: <pre> $ mkdir ~/stellarislaunchpad/ $ wget http://hobbyelektronik.org/w/images/d/d6/StellarisToolchainMakefile.h -O ~/stellarislaunchpad/Makefile </pre> Anschließend folgt das Herunterladen aller Sourcen. Diese haben entpackt eine Größe von ca. 1.4 GiB und liegen in dem Ordner "~/stellarislaunchpad/source". Zur Überprüfung sind hier die heruntergeladen Pakete aufgeführt. <pre> $ make initial -C ~/stellarislaunchpad/ ...... $ ls -1 ~/stellarislaunchpad/source/ binutils-2.22 gcc-4.9.0 gdb-7.8 lm4tools-master newlib-2.1.0 openocd-0.8.0 stellarisWare-master texinfo-5.2 </pre> Jetzt kann der eigentliche Bauvorgang gestartet werden. Dieser wird je nach Rechenleistung des Computers mehrere Stunden benötigen. Die Anzahl der Jobs, mit denen gebaut wird, berechnet sich automatisch aus der Anzahl der Prozessoren. Daher das "make" nicht mit mehreren Jobs starten! <pre> $ make all -C ~/stellarislaunchpad/ </pre> Das Ergebnis des Bauvorgangs mit Compiler, Gdb, lm4flash, usw. befindet sich in dem Ordner ~/stellarislaunchpad/. Die wichtigsten Binaries sind: <pre> ~/stellarislaunchpad/output/bin/arm-none-eabi-gcc # c compiler ~/stellarislaunchpad/output/bin/lm4flash # tool to programm the stellaris launchpad via usb ~/stellarislaunchpad/output/bin/arm-none-eabi-gdb # gdb ~/stellarislaunchpad/output/arm-none-eabi/sys-include/ # folder with useful header </pre> Nach diesem langwierigem Prozess des Bauens können wir uns endlich der Programmierung des Stellaris Launchpads widmen. Hierfür ist in dem Makefile ein Beispiel vorhanden. Dabei wird das "blinky" Projekt der Stellaris Ware gebaut und auf das Lauchpad gespielt. Dazu muss das Launchpad selbstverständlich am PC via USB eingesteckt sein. Leider ist es mir bis jetzt nicht gelungen, das lm4flash Tool ohne Rootrechte zu starten. Der Systemcall dazu lautet: <pre> $ sudo make example -C ~/stellarislaunchpad/ </pre> Ist alles gut gegangen, blinkt das Stellaris Launchpad nun fröhlich in grün vor sich hin. Bei der Stellaris Ware (unter ~/stellarisware/source/stellarisWare-master/) befinden sich noch viele weitere Beispiele, welche zum experimentieren einladen. =Erklärung des Makefiles= Im folgenden wird genauer auf die einzelnen Teile des Makefiles eingegangen. ==Verwendete Variablen== Die wichtigsten globalen Variablen des Makefiles werden hier kurz genannt. Nicht aufgeführt sind die Variablen für den Speicherort und Version der einzelnen Pakete. <pre> BASE = $(shell pwd) # the act. folder PREFIX = $(BASE)/output # install folder SOURCE = $(BASE)/source/ # source folder TARGET = arm-none-eabi # target name JOBS = $(shell cat /proc/cpuinfo | grep MHz | wc -l) # number of jobs for make MAKE = PATH=$(PREFIX)/bin:$${PATH} make -j $(JOBS) # make variable with modified path and the number of jobs </pre> ==Texinfo== Texinfo beinhaltet das Programm "makeinfo", welches beim Bauvorgang der Newlib benötigt wird. Nur aus diesem Grund wird dieses relativ kleine Software-Paket mit gebaut. <pre> texinfo: cd $(TEXINFO_DIR) && ./configure \ --prefix=$(PREFIX) $(MAKE) -C $(TEXINFO_DIR) all $(MAKE) -C $(TEXINFO_DIR) install </pre> ==Binutils== Die Binutils beinhalten eine Vielzahl an Werkzeugen, unter anderem zum übersetzen von Code. Mehr Informationen dazu gibt es auf der GNU-Website. <pre> binutils: cd $(BINUTILS_DIR) && ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --disable-nls \ --enable-multilib \ --with-gnu-as \ --with-gnu-ld \ --disable-libssp \ --disable-werror $(MAKE) -C $(BINUTILS_DIR) all $(MAKE) -C $(BINUTILS_DIR) install </pre> ==Gcc-initial== Nun wird der eigentliche Gcc Compiler gebaut. Dieser benötigt zum vollständigen Bauen eine Library mit grundlegenden Funktionen und den entsprechenden Header Dateien. Nachdem die glibc Library zu groß für Mikrocontroller ist, bietet sich Newlib an. Zum Bauen der Newlib muss allerdings ein Teil des Gcc bereits vorhanden sein, weshalb der Gcc in zwei Schritten gebaut wird. Hier die richtige Reihenfolge: # GCC-Configure # GCC-make all-gcc # GCC-make install-gcc # NEWLIB-configure # NEWLIB-make # NEWLIB-make install # GCC-make all # GCC-make install Erst nach dem erfolgreichen "make install" vom Gcc ist dieser komplett gebaut. Aber nun zu der Erklärung. Zu Beginn wird im Gcc-Verzeichnis ein neuer Ordner angelegt, weil man den Gcc nicht direkt in dem Verzeichnis der Sourcen bauen kann. Bei der Konfiguration werden eine Vielzahl an Features ausgeschaltet, welche auf dem Mikrocontroller nicht benötigt werden. Wichtig ist das setzen des "--enable-languages" Flag für die gewünschte Sprache. Dazu kommt natürlich das entsprechende Flag für die Newlib("--with-newlib"). Um diese zu verwenden, muss der Headerpfad zu der Newlib entsprechend angegeben werden("--with-headers"). Zudem ist auch die Angabe des CPU-Typs(cortex-m4) wichtig. <pre> gcc-initial: mkdir -p $(GCC_DIR)/build cd $(GCC_DIR)/build && PATH=$(PREFIX)/bin:$${PATH} ../configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-languages=c \ --disable-bootstrap \ --disable-libgomp \ --disable-libmudflap \ --enable-multilib \ --disable-libphobos \ --disable-decimal-float \ --disable-libffi \ --disable-libmudflap \ --disable-libquadmath \ --disable-libssp \ --disable-libstdcxx-pch \ --disable-nls \ --disable-shared \ --disable-threads \ --disable-tls \ --with-gnu-as \ --with-gnu-ld \ --with-cpu=cortex-m4 \ --with-tune=cortex-m4 \ --with-mode=thumb \ --with-newlib \ --with-headers=$(NEWLIB_DIR)/newlib/libc/include/ $(MAKE) -C $(GCC_DIR)/build/ all-gcc $(MAKE) -C $(GCC_DIR)/build/ install-gcc </pre> ==Newlib== Vor dem Bauen der Newlib muss die verwendete Version 2.1.0 noch gepatcht werden, weil sonst folgender Fehler auftritt: <pre> make[7]: Entering directory '/home/user/stellarislaunchpad/source/newlib-2.1.0/arm-none-eabi/thumb/libgloss/arm/cpu-init' make[7]: *** No rule to make target '../../../.././libgloss/arm/../config/default.mh', needed by 'Makefile'. Stop. </pre> Der Patch ist in das Makefile integriert und wird sofort nach Herunterladen der Sourcen eingespielt. Hier der Patch: <pre> --- libgloss/arm/cpu-init/Makefile.in 2013-10-14 17:15:12.000000000 +0200 +++ libgloss/arm/cpu-init/Makefile.in 2014-10-17 21:38:32.623317260 +0200 @@ -18,6 +18,7 @@ tooldir = $(exec_prefix)/$(target_alias) objtype = @objtype@ +host_makefile_frag = /../../config/default.mh INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -80,7 +81,7 @@ install-info: clean-info: -Makefile: Makefile.in ../config.status @host_makefile_frag_path@ +Makefile: Makefile.in ../config.status $${host_makefile_frag_path} $$(SHELL) ../config.status --file cpu-init/Makefile ../config.status: ../configure </pre> Zum Konfigurieren der Newlib gibt es nichts besonders zu erwähnen. Es wird wie beim Gcc natürlich auch unser Target angegeben. Wichtig ist beim installieren, dass hier nicht unsere "$(MAKE)" Variable verwendet wird. Da es sonst beim Verwenden mehrerer Jobs zu Problemen führen kann. <pre> newlib: cd $(NEWLIB_DIR) && PATH=$${PATH}/:$(PREFIX)/bin/ ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-multilib \ --disable-libssp \ --disable-nls $(MAKE) -C $(NEWLIB_DIR) all # use normal make without jobs because of issues with multiple jobs PATH=$(PREFIX)/bin:$${PATH} make -C $(NEWLIB_DIR) install </pre> ==Gcc-final== Endlich ist es so weit. Wir können unseren Compiler fertig bauen und installieren. Der Compiler befindet sich anschließend unter output/bin/arm-none-eabi-gcc und kann nun verwendet werden. <pre> gcc-final: $(MAKE) -C $(GCC_DIR)/build/ all $(MAKE) -C $(GCC_DIR)/build/ install </pre> ==Lm4flash== Zum Aufspielen der Software auf das Launchpad benötigt man die Lm4flash-tools. Diese brauchen zwingend das Paket libusb und das dazugehörige Developer Package. Unter Arch und Ubuntu können diese leicht über die Paketmanager installiert werden. <pre> lm4tools: echo "lm4tools needs libusb dev and pkg(try apt-get install libusb-dev)" make -C $(LM4TOOLS_DIR)/lm4flash cp $(LM4TOOLS_DIR)/lm4flash/lm4flash $(PREFIX)/bin/ </pre> Getestet werden kann Lm4flash einfach mit dem flash-blinky Beispiel des Makefiles. Dazu wird das blinky-Projekt der Stellarisware crosscompiliert und per lm4flash auf das Launchpad via USB gespielt. Möglicherweise wird zum Übertragen der Daten Rootrechte benötigt. <pre> blinky: $(MAKE) -C $(STELLARISWARE_DIR)/boards/ek-lm4f120xl/blinky/ flash-blinky: blinky $(PREFIX)/bin/lm4flash $(STELLARISWARE_DIR)/boards/ek-lm4f120xl/blinky/gcc/blinky.bin </pre> ==GDB== Zum Debuggen wird nun noch der entsprechende Gdb benötigt. Auch dieser kann ohne große Mühe gebaut werden. Hier wird nicht weiter auf den Gdb eingegangen, da es genügend ausführliche Anleitungen im Internet gibt. <pre> gdb: cd $(GDB_DIR) && ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-interwork \ --enable-multilib $(MAKE) -C $(GDB_DIR) all $(MAKE) -C $(GDB_DIR) install </pre> ==OpenOCD== Und für alle Freunde von OpenOCD wird der nötige Bauvorgang kurz gezeigt. Wichtig dabei ist das "--enable-ti-icdi" Flag. <pre> openocd: cd $(OPENOCD_DIR) && ./configure \ --prefix=$(PREFIX) \ --enable-maintainer-mode \ --enable-ti-icdi $(MAKE) -C $(OPENOCD_DIR) all $(MAKE) -C $(OPENOCD_DIR) install </pre> [[Kategorie:Software]] 4c719cbc889fa6bf8504fc65a8611531d05dcf74 958 957 2014-11-19T21:50:00Z Chris 2 bisschen aufgehübscht wikitext text/x-wiki Im folgenden wird beschrieben, wie man sich die Toolchain, Debugger und Flashtools zum Programmieren via USB für das Stellaris Launchpad von Grund auf selber baut. Die Idee dazu kam mir, als ich Probleme mit einem der 32bit Compiler von TI unter einem 64bit Betriebssystem hatten. Außerdem ist es natürlich deutlich "cooler", seine eigenen Compiler zu verwenden! So kann man bei Problemen auch einfach mal im Source Code stöbern. An dieser Stelle sei gesagt, das dieser Vorgang sehr rechen- und zeitintensiv ist und ihr während des Bauvorgangs deutlich über 10 Tassen Kaffee trinken könnt. Um Missverständnisse auszuräumen sei kurz erwähnt, dass dieses Tutorial für Linuxanwender gedacht ist und eine Portierung auf Windows schwer sein dürfe. Die komplette Software für die Toolchain kann mittels eines Makefiles ([[Datei:StellarisToolchainMakefile.h]]) heruntergeladen und gebaut werden. Am Anfang des Artikels wird die Verwendung dieses Makefiles erklärt. Danach wird auf die einzelnen Komponenten kurz eingegangen. <b>Warnung:</b> Die hier verwendeten Softwarepakete unterliegen verschiedensten Lizenzen, welche eingehalten müssen werden! =Bauen der Toolchain= Zu Beginn sollte man sich das Makefile herunterladen und in einem beliebigen Ordner speichern: <pre> $ mkdir ~/stellarislaunchpad/ $ wget http://hobbyelektronik.org/w/images/d/d6/StellarisToolchainMakefile.h -O ~/stellarislaunchpad/Makefile </pre> Anschließend folgt das Herunterladen aller Sourcen. Diese haben entpackt eine Größe von ca. 1.4 GiB und liegen in dem Ordner "~/stellarislaunchpad/source". Zur Überprüfung sind hier die heruntergeladen Pakete aufgeführt. <pre> $ make initial -C ~/stellarislaunchpad/ ...... $ ls -1 ~/stellarislaunchpad/source/ binutils-2.22 gcc-4.9.0 gdb-7.8 lm4tools-master newlib-2.1.0 openocd-0.8.0 stellarisWare-master texinfo-5.2 </pre> Jetzt kann der eigentliche Bauvorgang gestartet werden. Dieser wird je nach Rechenleistung des Computers mehrere Stunden benötigen. Die Anzahl der Jobs, mit denen gebaut wird, berechnet sich automatisch aus der Anzahl der Prozessoren. Daher das "make" nicht mit mehreren Jobs starten! <pre> $ make all -C ~/stellarislaunchpad/ </pre> Das Ergebnis des Bauvorgangs mit Compiler, Gdb, lm4flash, usw. befindet sich in dem Ordner ~/stellarislaunchpad/. Die wichtigsten Binaries sind: <pre> ~/stellarislaunchpad/output/bin/arm-none-eabi-gcc # c compiler ~/stellarislaunchpad/output/bin/lm4flash # tool to programm the stellaris launchpad via usb ~/stellarislaunchpad/output/bin/arm-none-eabi-gdb # gdb ~/stellarislaunchpad/output/arm-none-eabi/sys-include/ # folder with useful header </pre> Nach diesem langwierigem Prozess des Bauens können wir uns endlich der Programmierung des Stellaris Launchpads widmen. Hierfür ist in dem Makefile ein Beispiel vorhanden. Dabei wird das "blinky" Projekt der Stellaris Ware gebaut und auf das Lauchpad gespielt. Dazu muss das Launchpad selbstverständlich am PC via USB eingesteckt sein. Leider ist es mir bis jetzt nicht gelungen, das lm4flash Tool ohne Rootrechte zu starten. Der Systemcall dazu lautet: <pre> $ sudo make example -C ~/stellarislaunchpad/ </pre> Ist alles gut gegangen, blinkt das Stellaris Launchpad nun fröhlich in grün vor sich hin. Bei der Stellaris Ware (unter ~/stellarisware/source/stellarisWare-master/) befinden sich noch viele weitere Beispiele, welche zum experimentieren einladen. =Erklärung des Makefiles= Im folgenden wird genauer auf die einzelnen Teile des Makefiles eingegangen. ==Verwendete Variablen== Die wichtigsten globalen Variablen des Makefiles werden hier kurz genannt. Nicht aufgeführt sind die Variablen für den Speicherort und Version der einzelnen Pakete. <pre> BASE = $(shell pwd) # the act. folder PREFIX = $(BASE)/output # install folder SOURCE = $(BASE)/source/ # source folder TARGET = arm-none-eabi # target name JOBS = $(shell cat /proc/cpuinfo | grep MHz | wc -l) # number of jobs for make MAKE = PATH=$(PREFIX)/bin:$${PATH} make -j $(JOBS) # make variable with modified path and the number of jobs </pre> ==Texinfo== Texinfo beinhaltet das Programm "makeinfo", welches beim Bauen der Newlib benötigt wird. Nur aus diesem Grund wird dieses relativ kleine Software-Paket mit gebaut. <pre> texinfo: cd $(TEXINFO_DIR) && ./configure \ --prefix=$(PREFIX) $(MAKE) -C $(TEXINFO_DIR) all $(MAKE) -C $(TEXINFO_DIR) install </pre> ==Binutils== Die Binutils beinhalten eine Vielzahl an Werkzeugen, unter anderem zum Übersetzen von Code. Mehr Informationen dazu gibt es auf der [http://www.gnu.org/software/binutils/ GNU-Website]. <pre> binutils: cd $(BINUTILS_DIR) && ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --disable-nls \ --enable-multilib \ --with-gnu-as \ --with-gnu-ld \ --disable-libssp \ --disable-werror $(MAKE) -C $(BINUTILS_DIR) all $(MAKE) -C $(BINUTILS_DIR) install </pre> ==Gcc-initial== Nun wird der eigentliche Gcc Compiler gebaut. Dieser benötigt zum vollständigen Bauen eine Library mit grundlegenden Funktionen und den entsprechenden Header Dateien. Nachdem die glibc-Library zu groß für Mikrocontroller ist, bietet sich z. B. Newlib an. Zum Bauen der Newlib muss allerdings ein Teil des GCC bereits vorhanden sein, weshalb dieser in zwei Schritten gebaut werden muss. Die richtige Reihenfolge hierfür sit: # GCC-Configure # GCC-make all-gcc # GCC-make install-gcc # NEWLIB-configure # NEWLIB-make # NEWLIB-make install # GCC-make all # GCC-make install Erst nach dem erfolgreichen letzten Schritt ("make install") ist GCC komplett gebaut. Aber nun zu der Erklärung. Zu Beginn wird im GCC-Verzeichnis ein neuer Ordner angelegt, weil man den GCC nicht direkt in dem Verzeichnis der Sourcen bauen kann. Bei der Konfiguration werden eine Vielzahl an Features ausgeschaltet, welche auf dem Mikrocontroller nicht benötigt werden. Wichtig ist das Setzen des "--enable-languages" Flags für die gewünschte Sprache - in diesem Fall C. Dazu kommt natürlich das entsprechende Flag für die Newlib ("--with-newlib"). Um diese zu verwenden, muss zusätzlich der Headerpfad zu der Newlib angegeben werden ("--with-headers"). Zudem ist auch die Angabe des CPU-Typs (cortex-m4) wichtig. <pre> gcc-initial: mkdir -p $(GCC_DIR)/build cd $(GCC_DIR)/build && PATH=$(PREFIX)/bin:$${PATH} ../configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-languages=c \ --disable-bootstrap \ --disable-libgomp \ --disable-libmudflap \ --enable-multilib \ --disable-libphobos \ --disable-decimal-float \ --disable-libffi \ --disable-libmudflap \ --disable-libquadmath \ --disable-libssp \ --disable-libstdcxx-pch \ --disable-nls \ --disable-shared \ --disable-threads \ --disable-tls \ --with-gnu-as \ --with-gnu-ld \ --with-cpu=cortex-m4 \ --with-tune=cortex-m4 \ --with-mode=thumb \ --with-newlib \ --with-headers=$(NEWLIB_DIR)/newlib/libc/include/ $(MAKE) -C $(GCC_DIR)/build/ all-gcc $(MAKE) -C $(GCC_DIR)/build/ install-gcc </pre> ==Newlib== Vor dem Bauen der Newlib muss die verwendete Version 2.1.0 noch gepatcht werden, weil sonst folgender Fehler auftritt: <pre> make[7]: Entering directory '/home/user/stellarislaunchpad/source/newlib-2.1.0/arm-none-eabi/thumb/libgloss/arm/cpu-init' make[7]: *** No rule to make target '../../../.././libgloss/arm/../config/default.mh', needed by 'Makefile'. Stop. </pre> Der Patch ist in das Makefile integriert und wird sofort nach dem Herunterladen der Sourcen eingespielt: <source lang="diff"> --- libgloss/arm/cpu-init/Makefile.in 2013-10-14 17:15:12.000000000 +0200 +++ libgloss/arm/cpu-init/Makefile.in 2014-10-17 21:38:32.623317260 +0200 @@ -18,6 +18,7 @@ tooldir = $(exec_prefix)/$(target_alias) objtype = @objtype@ +host_makefile_frag = /../../config/default.mh INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -80,7 +81,7 @@ install-info: clean-info: -Makefile: Makefile.in ../config.status @host_makefile_frag_path@ +Makefile: Makefile.in ../config.status $${host_makefile_frag_path} $$(SHELL) ../config.status --file cpu-init/Makefile ../config.status: ../configure </source> Zum Konfigurieren der Newlib gibt es nichts besonders zu erwähnen. Es wird wie beim GCC natürlich auch unser Target angegeben. Wichtig ist beim Installieren, dass hier nicht unsere "$(MAKE)"-Variable verwendet wird, da es sonst beim Verwenden mehrerer Jobs zu Problemen kommen kann´. <pre> newlib: cd $(NEWLIB_DIR) && PATH=$${PATH}/:$(PREFIX)/bin/ ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-multilib \ --disable-libssp \ --disable-nls $(MAKE) -C $(NEWLIB_DIR) all # use normal make without jobs because of issues with multiple jobs PATH=$(PREFIX)/bin:$${PATH} make -C $(NEWLIB_DIR) install </pre> ==GCC-final== Endlich ist es so weit! Wir können unseren Compiler fertig bauen und installieren. Der Compiler befindet sich anschließend unter output/bin/arm-none-eabi-gcc und kann nun verwendet werden. <pre> gcc-final: $(MAKE) -C $(GCC_DIR)/build/ all $(MAKE) -C $(GCC_DIR)/build/ install </pre> ==Lm4flash== Zum Aufspielen der Software auf das Launchpad benötigt man die Lm4flash-tools. Diese brauchen zwingend das Paket libusb und das dazugehörige Developer-Package. Unter Arch und Ubuntu können diese leicht über die Paketmanager installiert werden. <pre> lm4tools: echo "lm4tools needs libusb dev and pkg(try apt-get install libusb-dev)" make -C $(LM4TOOLS_DIR)/lm4flash cp $(LM4TOOLS_DIR)/lm4flash/lm4flash $(PREFIX)/bin/ </pre> Getestet werden kann Lm4flash einfach mit dem flash-blinky Beispiel des Makefiles - dazu wird das blinky-Projekt der Stellarisware crosscompiliert und per lm4flash auf das Launchpad via USB gespielt. Möglicherweise werden zum Übertragen der Daten, wie bereits erwähnt, Rootrechte benötigt. <pre> blinky: $(MAKE) -C $(STELLARISWARE_DIR)/boards/ek-lm4f120xl/blinky/ flash-blinky: blinky $(PREFIX)/bin/lm4flash $(STELLARISWARE_DIR)/boards/ek-lm4f120xl/blinky/gcc/blinky.bin </pre> ==GDB== Zum Debuggen wird nun noch der entsprechende GDB benötigt. Auch dieser kann ohne große Mühe gebaut werden. Hier wird nicht weiter auf den Gdb eingegangen, da es dazu genügend ausführliche Anleitungen im Internet gibt. <pre> gdb: cd $(GDB_DIR) && ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-interwork \ --enable-multilib $(MAKE) -C $(GDB_DIR) all $(MAKE) -C $(GDB_DIR) install </pre> ==OpenOCD== Und für alle Freunde von OpenOCD wird der nötige Bauvorgang kurz gezeigt. Wichtig dabei ist das "--enable-ti-icdi"-Flag zu setzen: <pre> openocd: cd $(OPENOCD_DIR) && ./configure \ --prefix=$(PREFIX) \ --enable-maintainer-mode \ --enable-ti-icdi $(MAKE) -C $(OPENOCD_DIR) all $(MAKE) -C $(OPENOCD_DIR) install </pre> [[Kategorie:Software]] 906b0c8a4798960756bc6edfe20d949b7fafce07 959 958 2014-11-19T21:51:14Z Chris 2 Formulierung wikitext text/x-wiki Im folgenden wird beschrieben, wie man sich die Toolchain, Debugger und Flashtools zum Programmieren via USB für das Stellaris Launchpad von Grund auf selber baut. Die Idee dazu kam mir, als ich Probleme mit einem der 32bit Compiler von TI unter einem 64bit Betriebssystem hatten. Außerdem ist es natürlich deutlich "cooler", seine eigenen Compiler zu verwenden! So kann man bei Problemen auch einfach mal im Source Code stöbern. An dieser Stelle sei gesagt, das dieser Vorgang sehr rechen- und zeitintensiv ist und ihr während des Bauvorgangs deutlich über 10 Tassen Kaffee trinken könnt. Um Missverständnisse auszuräumen sei kurz erwähnt, dass dieses Tutorial für Linuxanwender gedacht ist und eine Portierung auf Windows schwer sein dürfe. Die komplette Software für die Toolchain kann mittels eines Makefiles ([[Datei:StellarisToolchainMakefile.h]]) heruntergeladen und gebaut werden. Am Anfang des Artikels wird die Verwendung dieses Makefiles erklärt. Danach wird auf die einzelnen Komponenten kurz eingegangen. <b>Warnung:</b> Die hier verwendeten Softwarepakete unterliegen verschiedensten Lizenzen, welche eingehalten müssen werden! =Bauen der Toolchain= Zu Beginn sollte man sich das Makefile herunterladen und in einem beliebigen Ordner speichern: <pre> $ mkdir ~/stellarislaunchpad/ $ wget http://hobbyelektronik.org/w/images/d/d6/StellarisToolchainMakefile.h -O ~/stellarislaunchpad/Makefile </pre> Anschließend folgt das Herunterladen aller Sourcen. Diese haben entpackt eine Größe von ca. 1.4 GiB und liegen in dem Ordner "~/stellarislaunchpad/source". Zur Überprüfung sind hier die heruntergeladen Pakete aufgeführt. <pre> $ make initial -C ~/stellarislaunchpad/ ...... $ ls -1 ~/stellarislaunchpad/source/ binutils-2.22 gcc-4.9.0 gdb-7.8 lm4tools-master newlib-2.1.0 openocd-0.8.0 stellarisWare-master texinfo-5.2 </pre> Jetzt kann der eigentliche Bauvorgang gestartet werden. Dieser wird je nach Rechenleistung des Computers mehrere Stunden benötigen. Die Anzahl der Jobs, mit denen gebaut wird, berechnet sich automatisch aus der Anzahl der Prozessoren. Daher das "make" nicht mit mehreren Jobs starten! <pre> $ make all -C ~/stellarislaunchpad/ </pre> Das Ergebnis des Bauvorgangs mit Compiler, Gdb, lm4flash, usw. befindet sich in dem Ordner ~/stellarislaunchpad/. Die wichtigsten Binaries sind: <pre> ~/stellarislaunchpad/output/bin/arm-none-eabi-gcc # c compiler ~/stellarislaunchpad/output/bin/lm4flash # tool to programm the stellaris launchpad via usb ~/stellarislaunchpad/output/bin/arm-none-eabi-gdb # gdb ~/stellarislaunchpad/output/arm-none-eabi/sys-include/ # folder with useful header </pre> Nach diesem langwierigem Prozess des Bauens können wir uns endlich der Programmierung des Stellaris Launchpads widmen. Hierfür ist in dem Makefile ein Beispiel vorhanden. Dabei wird das "blinky" Projekt der Stellaris Ware gebaut und auf das Lauchpad gespielt. Dazu muss das Launchpad selbstverständlich am PC via USB eingesteckt sein. Leider ist es mir bis jetzt nicht gelungen, das lm4flash Tool ohne Rootrechte zu starten. Der Systemcall dazu lautet: <pre> $ sudo make example -C ~/stellarislaunchpad/ </pre> Ist alles gut gegangen, blinkt das Stellaris Launchpad nun fröhlich in grün vor sich hin. Bei der Stellaris Ware (unter ~/stellarisware/source/stellarisWare-master/) befinden sich noch viele weitere Beispiele, welche zum experimentieren einladen. =Erklärung des Makefiles= Im folgenden wird genauer auf die einzelnen Teile des Makefiles eingegangen. ==Verwendete Variablen== Die wichtigsten globalen Variablen des Makefiles werden hier kurz genannt. Nicht aufgeführt sind die Variablen für den Speicherort und Version der einzelnen Pakete. <pre> BASE = $(shell pwd) # the act. folder PREFIX = $(BASE)/output # install folder SOURCE = $(BASE)/source/ # source folder TARGET = arm-none-eabi # target name JOBS = $(shell cat /proc/cpuinfo | grep MHz | wc -l) # number of jobs for make MAKE = PATH=$(PREFIX)/bin:$${PATH} make -j $(JOBS) # make variable with modified path and the number of jobs </pre> ==Texinfo== Texinfo beinhaltet das Programm "makeinfo", welches beim Bauen der Newlib benötigt wird. Nur aus diesem Grund wird dieses relativ kleine Software-Paket mit gebaut. <pre> texinfo: cd $(TEXINFO_DIR) && ./configure \ --prefix=$(PREFIX) $(MAKE) -C $(TEXINFO_DIR) all $(MAKE) -C $(TEXINFO_DIR) install </pre> ==Binutils== Die Binutils beinhalten eine Vielzahl an Werkzeugen, unter anderem zum Übersetzen von Code. Mehr Informationen dazu gibt es auf der [http://www.gnu.org/software/binutils/ GNU-Website]. <pre> binutils: cd $(BINUTILS_DIR) && ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --disable-nls \ --enable-multilib \ --with-gnu-as \ --with-gnu-ld \ --disable-libssp \ --disable-werror $(MAKE) -C $(BINUTILS_DIR) all $(MAKE) -C $(BINUTILS_DIR) install </pre> ==Gcc-initial== Nun wird der eigentliche Gcc Compiler gebaut. Dieser benötigt zum vollständigen Bauen eine Library mit grundlegenden Funktionen und den entsprechenden Header Dateien. Nachdem die glibc-Library zu groß für Mikrocontroller ist, bietet sich z. B. Newlib an. Zum Bauen der Newlib muss allerdings ein Teil des GCC bereits vorhanden sein, weshalb dieser in zwei Schritten gebaut werden muss. Die richtige Reihenfolge hierfür sit: # GCC-Configure # GCC-make all-gcc # GCC-make install-gcc # NEWLIB-configure # NEWLIB-make # NEWLIB-make install # GCC-make all # GCC-make install Erst nach dem erfolgreichen letzten Schritt ("make install") ist GCC komplett gebaut. Aber nun zu der Erklärung. Zu Beginn wird im GCC-Verzeichnis ein neuer Ordner angelegt, weil man den GCC nicht direkt in dem Verzeichnis der Sourcen bauen kann. Bei der Konfiguration werden eine Vielzahl an Features ausgeschaltet, welche auf dem Mikrocontroller nicht benötigt werden. Wichtig ist das Setzen des "--enable-languages" Flags für die gewünschte Sprache - in diesem Fall C. Dazu kommt natürlich das entsprechende Flag für die Newlib ("--with-newlib"). Um diese zu verwenden, muss zusätzlich der Headerpfad zu der Newlib angegeben werden ("--with-headers"). Zudem ist auch die Angabe des CPU-Typs (cortex-m4) wichtig. <pre> gcc-initial: mkdir -p $(GCC_DIR)/build cd $(GCC_DIR)/build && PATH=$(PREFIX)/bin:$${PATH} ../configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-languages=c \ --disable-bootstrap \ --disable-libgomp \ --disable-libmudflap \ --enable-multilib \ --disable-libphobos \ --disable-decimal-float \ --disable-libffi \ --disable-libmudflap \ --disable-libquadmath \ --disable-libssp \ --disable-libstdcxx-pch \ --disable-nls \ --disable-shared \ --disable-threads \ --disable-tls \ --with-gnu-as \ --with-gnu-ld \ --with-cpu=cortex-m4 \ --with-tune=cortex-m4 \ --with-mode=thumb \ --with-newlib \ --with-headers=$(NEWLIB_DIR)/newlib/libc/include/ $(MAKE) -C $(GCC_DIR)/build/ all-gcc $(MAKE) -C $(GCC_DIR)/build/ install-gcc </pre> ==Newlib== Vor dem Bauen der Newlib muss die verwendete Version 2.1.0 noch gepatcht werden, weil sonst folgender Fehler auftritt: <pre> make[7]: Entering directory '/home/user/stellarislaunchpad/source/newlib-2.1.0/arm-none-eabi/thumb/libgloss/arm/cpu-init' make[7]: *** No rule to make target '../../../.././libgloss/arm/../config/default.mh', needed by 'Makefile'. Stop. </pre> Der Patch ist in das Makefile integriert und wird sofort nach dem Herunterladen der Sourcen eingespielt: <source lang="diff"> --- libgloss/arm/cpu-init/Makefile.in 2013-10-14 17:15:12.000000000 +0200 +++ libgloss/arm/cpu-init/Makefile.in 2014-10-17 21:38:32.623317260 +0200 @@ -18,6 +18,7 @@ tooldir = $(exec_prefix)/$(target_alias) objtype = @objtype@ +host_makefile_frag = /../../config/default.mh INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -80,7 +81,7 @@ install-info: clean-info: -Makefile: Makefile.in ../config.status @host_makefile_frag_path@ +Makefile: Makefile.in ../config.status $${host_makefile_frag_path} $$(SHELL) ../config.status --file cpu-init/Makefile ../config.status: ../configure </source> Zum Konfigurieren der Newlib gibt es nichts besonders zu erwähnen. Es wird wie beim GCC natürlich auch unser Target angegeben. Wichtig ist beim Installieren, dass hier nicht unsere "$(MAKE)"-Variable verwendet wird, da es sonst beim Verwenden mehrerer Jobs zu Problemen kommen kann´. <pre> newlib: cd $(NEWLIB_DIR) && PATH=$${PATH}/:$(PREFIX)/bin/ ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-multilib \ --disable-libssp \ --disable-nls $(MAKE) -C $(NEWLIB_DIR) all # use normal make without jobs because of issues with multiple jobs PATH=$(PREFIX)/bin:$${PATH} make -C $(NEWLIB_DIR) install </pre> ==GCC-final== Endlich ist es so weit! Wir können unseren Compiler fertig bauen und installieren. Der Compiler befindet sich anschließend unter output/bin/arm-none-eabi-gcc und kann nun verwendet werden. <pre> gcc-final: $(MAKE) -C $(GCC_DIR)/build/ all $(MAKE) -C $(GCC_DIR)/build/ install </pre> ==Lm4flash== Zum Aufspielen der Software auf das Launchpad benötigt man die Lm4flash-tools. Diese brauchen zwingend das Paket libusb und das dazugehörige Developer-Package. Unter Arch und Ubuntu können diese leicht über die Paketmanager installiert werden. <pre> lm4tools: echo "lm4tools needs libusb dev and pkg(try apt-get install libusb-dev)" make -C $(LM4TOOLS_DIR)/lm4flash cp $(LM4TOOLS_DIR)/lm4flash/lm4flash $(PREFIX)/bin/ </pre> Getestet werden kann Lm4flash einfach mit dem flash-blinky Beispiel des Makefiles - dazu wird das blinky-Projekt der Stellarisware crosscompiliert und per lm4flash auf das Launchpad via USB gespielt. Möglicherweise werden zum Übertragen der Daten, wie bereits erwähnt, Rootrechte benötigt. <pre> blinky: $(MAKE) -C $(STELLARISWARE_DIR)/boards/ek-lm4f120xl/blinky/ flash-blinky: blinky $(PREFIX)/bin/lm4flash $(STELLARISWARE_DIR)/boards/ek-lm4f120xl/blinky/gcc/blinky.bin </pre> ==GDB== Zum Debuggen wird nun noch der entsprechende GDB benötigt. Auch dieser kann ohne große Mühe gebaut werden. Hier wird nicht weiter auf den Gdb eingegangen, da es dazu genügend ausführliche Anleitungen im Internet gibt. <pre> gdb: cd $(GDB_DIR) && ./configure \ --target=$(TARGET) \ --prefix=$(PREFIX) \ --enable-interwork \ --enable-multilib $(MAKE) -C $(GDB_DIR) all $(MAKE) -C $(GDB_DIR) install </pre> ==OpenOCD== Und für alle Freunde von OpenOCD kann auch diese Software für die Plattform kompiliert werden. Wichtig dabei ist das "--enable-ti-icdi"-Flag zu setzen: <pre> openocd: cd $(OPENOCD_DIR) && ./configure \ --prefix=$(PREFIX) \ --enable-maintainer-mode \ --enable-ti-icdi $(MAKE) -C $(OPENOCD_DIR) all $(MAKE) -C $(OPENOCD_DIR) install </pre> [[Kategorie:Software]] 8f9a26b91bbe7d114e7dd5808939d7bfae029a6f Stellaris Launchpad 0 389 954 2014-11-10T21:04:33Z Chris 2 verschob „[[Stellaris Launchpad]]“ nach „[[Stellaris Launchpad-Toolchain unter Linux]]“ wikitext text/x-wiki #WEITERLEITUNG [[Stellaris Launchpad-Toolchain unter Linux]] 1a490010b69eb100a3c75d6a75aefb1e8f0db03b Datei:Minipsu.zip 6 390 961 2015-04-01T17:23:59Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e 984 961 2015-04-04T20:44:12Z Chris 2 lud eine neue Version von „[[Datei:Minipsu.zip]]“ hoch wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v1 brd.png 6 391 962 2015-04-01T17:23:59Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v1 sch.png 6 392 963 2015-04-01T17:23:59Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v1 spannung last 1.png 6 393 964 2015-04-01T17:24:00Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v1 strompfad brd.png 6 394 965 2015-04-01T17:24:00Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v1 strompfad sch.png 6 395 966 2015-04-01T17:24:00Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v1 wirkungsgrad 1.png 6 396 967 2015-04-01T17:24:01Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v1 wirkungsgrad 2.png 6 397 968 2015-04-01T17:24:01Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v1 wirkungsgrad BAT54C.png 6 398 969 2015-04-01T17:24:01Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v1 wirkungsgrad CRS08.png 6 399 970 2015-04-01T17:24:01Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v2 brd.png 6 400 971 2015-04-01T17:24:02Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v2 sch.png 6 401 972 2015-04-01T17:24:02Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:Minipsu v2 strompfad brd.png 6 402 973 2015-04-01T17:24:02Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Mini-Schaltwandler 0 403 974 2015-04-01T17:28:45Z Chris 2 Seite erstellt wikitext text/x-wiki Mini-Schaltwandler Die meisten elektronischen Schaltungen haben eine geregelte Stromversorgung. Früher hat man dafür oft und gerne ein Bauteil aus der 78xx-Reihe verwendet. Ganz einfach, weil sie günstig sind, zuverlässig arbeiten und wenig Außenbeschaltung benötigen. Der große Nachteil an Linearreglern allgemein ist die in vielen Anwendungsfällen eher dürftige Effizienz und noch vielmehr die notwendige Kühlung, denn: Das Produkt aus Spannungsdifferenz zwischen Ein- und Ausgang und dem Strom, der durch den Regler fließt, ist ziemlich genau die Leistung, die man wegkühlen muss. Beispiel: ein 7805-Regler wird mit 12 V versorgt und soll eine Schaltung versorgen, die 200 mA benötigt: <math>P = \left(U_{\textrm{in}}-U_{\textrm{out}}\right) \cdot I = \left(12\textrm{ V}-5\textrm{ V}\right) \cdot 0.2 \textrm{ A} = 1.4\textrm{ W}</math> Nicht weltbeltbewegend, aber immerhin. Die Effizienz von diesem Regler liegt bei <math>\eta = \frac{P_\textrm{out}}{P_\textrm{in}}= \frac{U_\textrm{out} \cdot I_\textrm{out}}{U_\textrm{in} \cdot I_\textrm{in}}</math> wobei der Eigenbedarf der meisten Linearregler vernachlässigbar gering ist (also der Unterschied zwischen I_out und I_in), somit lassen sich die Ströme einfach kürzen und die Effizienz ist rein von den Spannungen abhängig. Im Beispiel oben ergibt sich ein Wirkungsgrad von etwa 42 %. Ziemlich mies. Mit einem Abwärtswandler (auch step-down- oder buck-converter) kann man mit - im Vergleich zu Linearreglern - etwas größerem Schaltungsaufwand deutlich bessere Ergebnisse erzielen. Dabei wird der Strom "zerhackt" und über ein Speicherelement (in aller Regel eine Induktivität) geglättet. Die Ausgangsspannung hängt dabei vom Tastverhältnis des Schalters ab. Vereinfacht gesagt: je länger dieser geschlossen ist, desto mehr Energie wird vom Eingang zum Ausgang transportiert. Der Wirkungsgrad hängt bei hierbei von mehreren Faktoren ab: * Schalttransistor * Freilaufdiode * Induktivität So toll das Prinzip ist, es hat nicht nur Vorteile. Beispielsweise hat man höhere Anforderungen an das Layout und Risiken, wenn es um das Bestehen von EMV-Zulassungen geht. Schließlich leben diese Schaltungen von steilen Flanken und mitunter kurzzeitig hohen Strömen. Außerdem sieht man am Ausgang oft deutlich größere Störungen als bei Linearreglern. Hinzu kommt noch, dass Schaltwandler aufgrund ihres Aufbaus deutlich Lastspezifischer sind. Sie sind als nicht DIE Lösung für eine Stromversorgung, sondern eine mögliche Art dafür. =Der Mini-Schaltwandler (Version 1)= Ich wollte einen kleinen und halbwegs flexibel einsetzbaren Schaltwandler haben, den man statt einem 78xx verwenden kann, natürlich nicht zu teuer. In Sachen Leistung ruhig mit Abstrichen - die meisten Anwendungen benötigen selten über 0,5 A. Eingangsspannung bis 20 V sollte ok sein, gerne aber auch etwas mehr. =Bauteilauswahl= Bei der Suche bei Farnell bin ich schnell fündig geworden: Der [http://www.microchip.com/wwwproducts/devices.aspx?dDocName=en554058 MCP16301] von Microchip. Im SOT-23-6-Gehäuse ist er zwar klein, aber noch gut per Hand lötbar, der Eingangsspannungsbereich ist angenehm groß. Der Ausgangsstrom ist mit 0,6 A mehr als hinreichend und die 500 kHz Schaltfrequenz erfordern eine relativ kleine Induktivität. Der Preis ist mit etwas um einen Euro fair. Und zu guter Letzt ist er mittlerweile auch bei Reichelt verfügbar. Nach dem IC kommt die Induktivität. Abschnitt 5.6 gibt einige Hinweise zur Auswahl samt Beispiele. Für den interessanten Bereich zwischen 2,0 bis 5 V Ausgangsspannung sollen es also 10 bis 22 µH sein und ein Sättigungsstrom von mindestens 760 mA wird empfohlen. Kurz durch den Reichelt-Katalog geblättert finden sich die Fastron 1616 FPS. Da mein Ziel erst einmal 3,3 V sind, soll es die 15 µH-Variante werden, wobei es auch passende mit 22 und 33 µH gibt. Leider wird der kleine Footprint von 4,2 x 4,2 mm² durch einen etwas schlechteren ESR erkauft. Wer Platz hat, greift lieber zur 242408 oder 242418 - diese versprechen eine etwas höhere Effizienz! Fehlt noch die Schaltdiode als Kernkomponente. Diese sollte klein und schnell sein und etwa 1 A können. Bei der Spannungsfestigkeit sollten 30 V reichen - mehr kann der MCP eh nicht. Die [http://www.reichelt.de/index.html?ACTION=3&GROUPID=2991&ARTICLE=146621 SS 13L] von Taiwan Semiconductor passt. Zur Glättung empfiehlt das Datenblatt 1 µF bis 10 µF am Eingang und 10 µF bis 22 µF am Ausgang (wobei es zwischen den Application Examples und der Empfehlung in Tabelle 5-2 etwas widersprüchlich ist). Um es generisch zu halten: 10 µF am Eingang, 22 µF am Ausgang. Hat Reichelt jeweils im 1206-Package, ist aber leider nicht so ganz billig. Wer Zugriff auf Farnell hat, bekommt mehr und vermutlich auch eine günstigere Auswahl. Der Schaltwandler-IC verwendet einen n-Kanal-FET als Schalter. Da sich dieser - wie von der Topologie gefordert - auf der High-Side befinden und U<sub>GS</sub> > U<sub>th</sub> sein muss, wird eine Hilfsspannung größer als U<sub>in</sub> benötigt. Eine Schaltung mit p-Kanal-FET wäre zwar sicher einfacher, würde aber leichte Abstriche im Wirkungsgrad bedeuten (idR. höherer R<sub>ds,on</sub>). Wie dem auch sei, die Hilfsspannung bekommt man fast geschenkt, indem man den Schalttransistor und die Induktivität als Ladungspumpe verwendet. Dazu benötigt man zusätzlich lediglich eine Diode und einen Kondensator. Damit das auch funktioniert, darf der FET nie durchgängig eingeschaltet sein - sonst wird nichts mehr gepumpt und er kann nicht mehr geschaltet werden. Da die benötigte Leistung durchweg niedrig ist, reichen Wald- und Wiesenkomponenten. Wie im Datenblatt vorgeschlagen eine 1N4148 und ein 100 nF-Kerko. Fehlen noch die Feedback-Widerstände. Um das verwenden zu können, was vielleicht sogar in der Grabbelkiste liegt, empfehle ich das Tool [http://www.muellerzumhagen.de/index.php/sascha/tools/widerstand-ist-zwecklos Widerstand ist Zwecklos], das direkt ein Werkzeug zum Ermitteln von Widerständen für Spannungsregler bietet. Vref ist mit 0,8 V zu wählen. Für 3,3 V gibt es aus der E6-Reihe ein sehr gut passendes Pärchen, für 5 V muss man entweder auf die E24-Reihe ausweichen, oder 3 Widerstände verwenden: {| class="wikitable" |- ! U<sub>out,target</sub> [V] !! Reihe !! R<sub>upper</sub> [Ohm] !! R<sub>lower</sub> [Ohm] !! U<sub>out</sub> (worst case) [V] |- | 3,3 || E6 || 47 k || 15 k || 3,307 (3,249 ... 3,349) |- | 5 || E24 || 27 k || 5,1 k || 5,035 (4,942 ... 5,111) |- | 5 || E24 || 36 k || 6,8 k || 5,035 (4,939 ... 5,108) |- | 5 || E6 || 33 k p 100 k || 4,7 k || 5,0233 (4,942 ... 5,111) |- | 5 || E6 || 47 k p 150 k || 6,8 k || 5,0102 (4,930 ... 5,098) |- |} Es ergibt sich folgende BOM: {| class="wikitable" |- ! Komponente !! Menge !! Reichelt Bestellname !! Preis [€] !! Farnell Bestellnummer !! Preis [€] |- | Microchip MCP16301 || 1 || MCP 16301T-I/CHY || 1,15 || 2009288 || 1,21 |- | Fastron 1616FPS 15µH || 1 || L-1616FPS 15µ || 0,22 || 2345178* || 1,15 |- | TSC SS13L || 1 || SS 13L || 0,11 || 1559158 || 0,1 |- | 1N4148 || 1 || 1N 4148 SMD || 0,02 || 1612361 || 0,04 |- | 100nF-Kerko || 1 || X7R-G0603 100N || 0,15 || * || 0,01 |- | 10µF/25V || 1 || X7R-G1206 10/25 || 0,24 || * || 0,25 |- | 22µF/6V || 1 || X5R-G0805 22/6 || 0,07 || * || 0,15 |- | 47kOhm 0603 || 1 || SMD-0603 47K || 0,1 || * || 0,01 |- | 15kOhm 0603 || 1 || SMD-0603 15K || 0,1 || * || 0,01 |- |} Für die Induktivität habe ich bei Farnell eine halbwegs gleichwertige ausgewählt, bei den Nicht-Kernkomponenten habe stehen die jeweils annehmbaren Preise ohne auf ein spezielles Produkt zu verweisen. Bei Reichelt kosten die Bauteile für einen Schaltregler 2,16 Euro, bei Farnell (inkl. MwSt.) 2,93 Euro. Trotzdem kann sich (bis auf die Spule) der Kauf bei Farnell - sofern man dort bestellen kann - durch die Preisstaffeln lohnen. =Stromlaufplan= Der Stromlaufplan ist reichlich unspektakulär, er ist nicht viel mehr als eine der Application Notes im Datenblatt. <gallery> Datei:minipsu_v1_sch.png|Stromlaufplan des Schaltreglers </gallery> =Layout= Das Layout ist da ein bisschen aufwändiger. Wie in der Einleitung angedeutet, soll es ein Ersatz für die 78xx werden. Das heißt: gleicher Formfaktor. Laut einem zufällig herausgezogenen [http://www.ti.com/lit/ds/symlink/lm340-n.pdf Datenblatt] ist das Package in im Mittel 10,16 x 14,99 mm² groß und 4,58 mm dick. Das gilt es anzustreben. Der Anschluss erfolgt, wie schon im Stromlaufplan zu sehen ist, über eine zweireihige Stiftleiste, die der Pinbelegung der gängigen Regler folgt. Der Konnektor ist allerdings nicht stehend, sondern liegend am Rand der Leiterkarte vorgesehen (demnächst in der [[EAGLE-Bibliotheken|EAGLE-Bibliothek]] verfügbar). Selbstverständlich muss man keine 6-polige Stiftleiste anlöten, es reicht eine dreipolige. Wenn überhaupt. Mit entsprechenden Pads auf der Hauptplatine kann man den Regler entweder stehend auflöten oder über eine Stiftleiste durch die Durchkontaktierungen auch liegend montieren. Möchte man sich die Stiftleiste sparen, kann man das Modul auch auf Höhe der Durchkontaktierungen absägen und an diesen liegend über die nun offengelegten Pads am Leiterkartenrand befestigen. Die Anschlussbelegung hat schon eine nicht zu unterschätzende Auswirkung auf die Platzierung der restlichen Bauteile. Gleichzeitig muss man auf allgemeine Designregeln für Schaltwandler achten - [http://www.lothar-miller.de/s9y/categories/40-Layout-Schaltregler Lothar Miller] hat hierfür einen sehr guten Artikel geschrieben. Um diesen Regeln gerecht zu werden hilf nur: Platzieren, überprüfen, neu platzieren, nochmal überprüfen und das behalten, mit dem man am wenigsten unglücklich ist. Das perfekte Design schafft man wohl nur extrem selten. Denn: wenn es in Bezug auf Strompfade gut ist, kann einem die Thermik oder die Platzierung von anderen Modulen (ok, hier nicht) in die Suppe spucken. Ich bin bei folgendem Layout angekommen: <gallery> Datei:minipsu_v1_brd.png|Layout des Schaltreglers </gallery> Außenmaße: 10,41 x 15,08 mm². Nur ein kleines bisschen oberhalb des gesteckten Ziels aber noch innerhalb der mechanischen Specs von TI ;-) Manche werden sich vielleicht fragen, warum die Ausgangsspannung über die untere Lage zum Spannungsteiler für das Feedback führt - das könnte man doch direkt an der Diode rechts oben abgreifen.... Ja, könnte man machen, aber dann wär's halt kacke. Abgesehen von dem blöden Spruch gibt es natürlich auch einen sinnvollen Grund dafür: Wo Strom fließt, fällt Spannung ab. An der Diode oben bzw. nahe an der Induktivität fließen mitunter etwas größere Ströme - wodurch sich die Messung verfälschen könnte. In der Praxis könnte man zwar probieren, ob es auch so geht, aber es gibt 1. keine Notwendigkeit dafür und 2. hat man bei anderen Designs weniger Probleme, wenn man sich gleich an vernünftiges Sensing gewöhnt. ==Betrachtung der Strompfade== Anhand der Millerschen Strompfadbilder lässt sich relativ leicht ermitteln, ob man einen groben Schnitzer im Design hat. Interessant sind die Strompfade in den drei verschiedenen Phasen des Schaltwandlers, die ich wie folgt sowohl im Stromlaufplan als auch im Layout hervorgehoben habe: * Laden: gelb * Freilauf/Leerlauf: orange * Recovery: blau <gallery> Datei:minipsu_v1_strompfad_sch.png|Strompfad im Stromlaufplan Datei:minipsu_v1_strompfad_brd.png|Strompfad im Layout </gallery> Das sieht schon ganz ok aus, wenn auch noch nicht optimal. Die Strecke links von C1 zu IC1 ist verhältnismäßig lang. Das gibt unnötige Induktivität, Widerstand und Abstrahlfläche. Dafür ist alles wichtige des Schaltwandlers auf einer Lage, was ebenfalls die Fläche klein hält. Unter der Induktivität befindet sich auf gleicher Lage Freischnitt des Kupfers. Leiterbahnen sollte man selbstverständlich soweit wie es geht fern halten. Bezüglich Aussparungen des Kupfers auf der/den anderen Lage(n) kann man streiten. Hier steht Einkopplung von Störströmen auf andere Signale oder die Massefläche und das Abblocken des Feldes (EMV) nach außen auf im Gegensatz... Hier ist noch anzumerken, dass das Layout der Leiterkarten leicht unterschiedlich zu den hier gezeigten Fotos ist. ==Aufbau== Ein paar Wochen später sind die gefertigten Leiterkarten auch [http://hobbyelektronik.org/b/2014/10/sie-sind-da/ angekommen] - ein paar Monate später wurden dann auch die Bauteile bestellt. Für die Bestückung sind etwas Feingefühl und eine dünne Lötspitze gefragt. ==Messungen== Keine Behauptungen ohne Beweise, in diesem Fall Messungen. Mit dem Labornetzteil und meinem einfachen DMM ließ sich grundlegend bestätigen: Ja, es funktioniert! Bei den festgelegten 3,3 V Ausgangsspannung fing der Regler bei etwa 3,7 V an, vernünftig zu arbeiten. Das hat zwei Gründe: Wie oben beschrieben, muss der Duty Cycle < 100 % sein, damit die Ladungspumpe zur Erzeugung der Hilfsspannung funktioniert. Nachdem der Maximum Duty Cycle bei typ. 95 % liegt, kann man ganz plump 3,7 V * 0,95 rechnen und landet bei 3,5 Volt. Dann kommt natürlich noch der R<sub>ds,on</sub> des FET und der Innenwiderstand der Induktivität sowie Schaltverluste dazu. Alles in allem: plausibel. Ein wichtiges Merkmal für den Betrieb ist natürlich der Wirkungsgrad. Dazu ermittelt man sowohl auf Ein- als auch Ausgangsseite die Leistung (indem man Strom und Spannung misst) bei bekannter Last und wendet die in der Einleitung gezeigte Formel an. Dies führt man mit verschiedenen Lasten und Eingangsspannungen durch, schmeißt die Daten in die Tabellenkalkulation und lässt es sich plotten: <gallery> Datei:minipsu_v1_wirkungsgrad_1.png|Wirkungsgrad über Last und Eingangsspannung Muster 1 Datei:minipsu_v1_wirkungsgrad_2.png|Wirkungsgrad über Last und Eingangsspannung Muster 2 </gallery> In dem Aufbau habe ich leicht abweichende Widerstandspaarungen als in der oben gezeigten Tabelle verwendet, was allerdings weitestgehend unmaßgeblich ist. Im Diagramm sieht man recht gut, dass mit 92 % der höchste Wirkungsgrad bei 5 V Eingangsspannung und einer Last von 100 mA erreicht wird. Bei den anderen Eingangsspannungen sieht es leider nicht ganz so gut aus. Zudem gibt es bei ca. 0,3 A einen leichten systematischen Einbruch (den ich auch mit einer zweiten Leiterkarte bestätigen konnte). Momentan kann ich allerdings nur mutmaßen, woher das kommt. Aus den Aufzeichnungen lässt sich auch das Verhalten die Ausgangsspannung unter Last darstellen: [[Datei:minipsu_v1_spannung_last_1.png]] Leider war die Auflösung (10 mV) relativ gering, dadurch der Treppeneffekt. Wie man sieht, ist das Verhalten durchaus hinnehmbar. ==Optimierung== Es ist noch nicht Ende Fahnenstange - aus dem Design kann man sicher mehr herauskitzeln. Die größten Kandidaten sind sicherlich die Induktivität und die Freilaufdiode, dann kommen irgendwann die Kondensatoren. Man könnte natürlich auch den IC austauschen, aber dann hat man zwangsläufig ein anderes Design. Ein weiterer Punkt wäre die Diode in der Boost-Schaltung - leckt diese zu stark, kann der FET evtl. nicht vollständig durchschalten. Da gerade keine passenden Alternativen für Induktivität und Kondensatoren herumliegen, bleiben nur noch die Dioden. Als Schaltdiode liegt noch eine [https://www.toshiba.com/taec/components2/Datasheet_Sync/200612/DST_CRS08-TDE_EN_1640.pdf CRS08 von Toshiba], für die Boost-Diode eine [http://www.vishay.com/docs/85508/bat54v.pdf BAT54] (Schottky) herum. <gallery> Datei:minipsu_v1_wirkungsgrad_CRS08.png|CRS08 als Schaltdiode Datei:minipsu_v1_wirkungsgrad_BAT54C.png|BAT54 als Boost-Diode </gallery> Die CRS08 reißt im Mittel einen 0,6 % höheren Wirkungsgrad heraus, die BAT54 0,4 %. Mal ganz abgesehen von Messungenauigkeiten oder Wiederholbarkeit... Für die eine andere Spule muss ich auf den nächsten Karton aus Sande warten, verspreche mir aber noch eine leichte Verbesserung. =Version 2= Es geht kleiner und ein bisschen besser. ==Layout== Die BAT43WS kostet unwesentlich mehr und dürfte die Performance ein kleines Stück verbessern - gleichzeitig ist sie ein gutes Stück kleiner als die die Diode in Minimelf-Gehäuse. Der Eingangs-Kondensator ist nach ist gedreht und etwas nach oben gewandert. Das erfordert zwar, dass die Versorgung über Durchkontaktierungen geführt wird, was an dieser Stelle relativ unproblematisch sein sollte. Durch das Verschieben kann sowohl die Schaltdiode als auch der IC nach unten verschoben werden. <gallery> Datei:minipsu_v2_sch.png|Stromlaufplan von Version 2 Datei:minipsu_v2_brd.png|Layout von Version 2 </gallery> Größe: 9,6 x 13,7 mm² Auf der Unterseite befindet sich nun im Silkscreen eine Tabelle für die gesetzte Spannung: 3,3 V, 5 V und ein freies Feld. Ferner gibt es für die liegende Montage auf der gegenüberliegenden Seite der Anschlüsse noch ein mit der Masse verbundenes Lötpad. ==Betrachtung der Strompfade== Neuer Anlauf: <gallery> Datei:minipsu_v2_strompfad_brd.png|Strompfad im Layout </gallery> Die Pfade sind jetzt deutlich kürzer. Die geringere Fläche dürfte mechanisch aber stärker wiegen als die der Einfluss auf die EMV... =Downloads= [[Datei:minipsu.zip]] =Weblinks= * [http://schmidt-walter-schaltnetzteile.de/smps/smps.html Dr. Schmidt-Walter - Dimensionierung von Schaltnetzteilen] * [http://powerelectronics.com/site-files/powerelectronics.com/files/archive/powerelectronics.com/mag/606PET25.pdf D. Schelle und J. Castorenoa - Buck-Converter Design Demystified] [[Kategorie:Elektronik]] [[Kategorie:Stromversorgung]] 9dedd2b7006fc36c9c62edd2dc9a61d02f792a5f 976 974 2015-04-01T17:42:30Z Chris 2 Doppelten Titel entfernt, Foto hinzugefügt wikitext text/x-wiki [[Datei:Datei:Minipsu v1 foto.jpg|thumb|Mini-Schaltwandler neben einem 7805]] Die meisten elektronischen Schaltungen haben eine geregelte Stromversorgung. Früher hat man dafür oft und gerne ein Bauteil aus der 78xx-Reihe verwendet. Ganz einfach, weil sie günstig sind, zuverlässig arbeiten und wenig Außenbeschaltung benötigen. Der große Nachteil an Linearreglern allgemein ist die in vielen Anwendungsfällen eher dürftige Effizienz und noch vielmehr die notwendige Kühlung, denn: Das Produkt aus Spannungsdifferenz zwischen Ein- und Ausgang und dem Strom, der durch den Regler fließt, ist ziemlich genau die Leistung, die man wegkühlen muss. Beispiel: ein 7805-Regler wird mit 12 V versorgt und soll eine Schaltung versorgen, die 200 mA benötigt: <math>P = \left(U_{\textrm{in}}-U_{\textrm{out}}\right) \cdot I = \left(12\textrm{ V}-5\textrm{ V}\right) \cdot 0.2 \textrm{ A} = 1.4\textrm{ W}</math> Nicht weltbeltbewegend, aber immerhin. Die Effizienz von diesem Regler liegt bei <math>\eta = \frac{P_\textrm{out}}{P_\textrm{in}}= \frac{U_\textrm{out} \cdot I_\textrm{out}}{U_\textrm{in} \cdot I_\textrm{in}}</math> wobei der Eigenbedarf der meisten Linearregler vernachlässigbar gering ist (also der Unterschied zwischen I_out und I_in), somit lassen sich die Ströme einfach kürzen und die Effizienz ist rein von den Spannungen abhängig. Im Beispiel oben ergibt sich ein Wirkungsgrad von etwa 42 %. Ziemlich mies. Mit einem Abwärtswandler (auch step-down- oder buck-converter) kann man mit - im Vergleich zu Linearreglern - etwas größerem Schaltungsaufwand deutlich bessere Ergebnisse erzielen. Dabei wird der Strom "zerhackt" und über ein Speicherelement (in aller Regel eine Induktivität) geglättet. Die Ausgangsspannung hängt dabei vom Tastverhältnis des Schalters ab. Vereinfacht gesagt: je länger dieser geschlossen ist, desto mehr Energie wird vom Eingang zum Ausgang transportiert. Der Wirkungsgrad hängt bei hierbei von mehreren Faktoren ab: * Schalttransistor * Freilaufdiode * Induktivität So toll das Prinzip ist, es hat nicht nur Vorteile. Beispielsweise hat man höhere Anforderungen an das Layout und Risiken, wenn es um das Bestehen von EMV-Zulassungen geht. Schließlich leben diese Schaltungen von steilen Flanken und mitunter kurzzeitig hohen Strömen. Außerdem sieht man am Ausgang oft deutlich größere Störungen als bei Linearreglern. Hinzu kommt noch, dass Schaltwandler aufgrund ihres Aufbaus deutlich Lastspezifischer sind. Sie sind als nicht DIE Lösung für eine Stromversorgung, sondern eine mögliche Art dafür. =Der Mini-Schaltwandler (Version 1)= Ich wollte einen kleinen und halbwegs flexibel einsetzbaren Schaltwandler haben, den man statt einem 78xx verwenden kann, natürlich nicht zu teuer. In Sachen Leistung ruhig mit Abstrichen - die meisten Anwendungen benötigen selten über 0,5 A. Eingangsspannung bis 20 V sollte ok sein, gerne aber auch etwas mehr. =Bauteilauswahl= Bei der Suche bei Farnell bin ich schnell fündig geworden: Der [http://www.microchip.com/wwwproducts/devices.aspx?dDocName=en554058 MCP16301] von Microchip. Im SOT-23-6-Gehäuse ist er zwar klein, aber noch gut per Hand lötbar, der Eingangsspannungsbereich ist angenehm groß. Der Ausgangsstrom ist mit 0,6 A mehr als hinreichend und die 500 kHz Schaltfrequenz erfordern eine relativ kleine Induktivität. Der Preis ist mit etwas um einen Euro fair. Und zu guter Letzt ist er mittlerweile auch bei Reichelt verfügbar. Nach dem IC kommt die Induktivität. Abschnitt 5.6 gibt einige Hinweise zur Auswahl samt Beispiele. Für den interessanten Bereich zwischen 2,0 bis 5 V Ausgangsspannung sollen es also 10 bis 22 µH sein und ein Sättigungsstrom von mindestens 760 mA wird empfohlen. Kurz durch den Reichelt-Katalog geblättert finden sich die Fastron 1616 FPS. Da mein Ziel erst einmal 3,3 V sind, soll es die 15 µH-Variante werden, wobei es auch passende mit 22 und 33 µH gibt. Leider wird der kleine Footprint von 4,2 x 4,2 mm² durch einen etwas schlechteren ESR erkauft. Wer Platz hat, greift lieber zur 242408 oder 242418 - diese versprechen eine etwas höhere Effizienz! Fehlt noch die Schaltdiode als Kernkomponente. Diese sollte klein und schnell sein und etwa 1 A können. Bei der Spannungsfestigkeit sollten 30 V reichen - mehr kann der MCP eh nicht. Die [http://www.reichelt.de/index.html?ACTION=3&GROUPID=2991&ARTICLE=146621 SS 13L] von Taiwan Semiconductor passt. Zur Glättung empfiehlt das Datenblatt 1 µF bis 10 µF am Eingang und 10 µF bis 22 µF am Ausgang (wobei es zwischen den Application Examples und der Empfehlung in Tabelle 5-2 etwas widersprüchlich ist). Um es generisch zu halten: 10 µF am Eingang, 22 µF am Ausgang. Hat Reichelt jeweils im 1206-Package, ist aber leider nicht so ganz billig. Wer Zugriff auf Farnell hat, bekommt mehr und vermutlich auch eine günstigere Auswahl. Der Schaltwandler-IC verwendet einen n-Kanal-FET als Schalter. Da sich dieser - wie von der Topologie gefordert - auf der High-Side befinden und U<sub>GS</sub> > U<sub>th</sub> sein muss, wird eine Hilfsspannung größer als U<sub>in</sub> benötigt. Eine Schaltung mit p-Kanal-FET wäre zwar sicher einfacher, würde aber leichte Abstriche im Wirkungsgrad bedeuten (idR. höherer R<sub>ds,on</sub>). Wie dem auch sei, die Hilfsspannung bekommt man fast geschenkt, indem man den Schalttransistor und die Induktivität als Ladungspumpe verwendet. Dazu benötigt man zusätzlich lediglich eine Diode und einen Kondensator. Damit das auch funktioniert, darf der FET nie durchgängig eingeschaltet sein - sonst wird nichts mehr gepumpt und er kann nicht mehr geschaltet werden. Da die benötigte Leistung durchweg niedrig ist, reichen Wald- und Wiesenkomponenten. Wie im Datenblatt vorgeschlagen eine 1N4148 und ein 100 nF-Kerko. Fehlen noch die Feedback-Widerstände. Um das verwenden zu können, was vielleicht sogar in der Grabbelkiste liegt, empfehle ich das Tool [http://www.muellerzumhagen.de/index.php/sascha/tools/widerstand-ist-zwecklos Widerstand ist Zwecklos], das direkt ein Werkzeug zum Ermitteln von Widerständen für Spannungsregler bietet. Vref ist mit 0,8 V zu wählen. Für 3,3 V gibt es aus der E6-Reihe ein sehr gut passendes Pärchen, für 5 V muss man entweder auf die E24-Reihe ausweichen, oder 3 Widerstände verwenden: {| class="wikitable" |- ! U<sub>out,target</sub> [V] !! Reihe !! R<sub>upper</sub> [Ohm] !! R<sub>lower</sub> [Ohm] !! U<sub>out</sub> (worst case) [V] |- | 3,3 || E6 || 47 k || 15 k || 3,307 (3,249 ... 3,349) |- | 5 || E24 || 27 k || 5,1 k || 5,035 (4,942 ... 5,111) |- | 5 || E24 || 36 k || 6,8 k || 5,035 (4,939 ... 5,108) |- | 5 || E6 || 33 k p 100 k || 4,7 k || 5,0233 (4,942 ... 5,111) |- | 5 || E6 || 47 k p 150 k || 6,8 k || 5,0102 (4,930 ... 5,098) |- |} Es ergibt sich folgende BOM: {| class="wikitable" |- ! Komponente !! Menge !! Reichelt Bestellname !! Preis [€] !! Farnell Bestellnummer !! Preis [€] |- | Microchip MCP16301 || 1 || MCP 16301T-I/CHY || 1,15 || 2009288 || 1,21 |- | Fastron 1616FPS 15µH || 1 || L-1616FPS 15µ || 0,22 || 2345178* || 1,15 |- | TSC SS13L || 1 || SS 13L || 0,11 || 1559158 || 0,1 |- | 1N4148 || 1 || 1N 4148 SMD || 0,02 || 1612361 || 0,04 |- | 100nF-Kerko || 1 || X7R-G0603 100N || 0,15 || * || 0,01 |- | 10µF/25V || 1 || X7R-G1206 10/25 || 0,24 || * || 0,25 |- | 22µF/6V || 1 || X5R-G0805 22/6 || 0,07 || * || 0,15 |- | 47kOhm 0603 || 1 || SMD-0603 47K || 0,1 || * || 0,01 |- | 15kOhm 0603 || 1 || SMD-0603 15K || 0,1 || * || 0,01 |- |} Für die Induktivität habe ich bei Farnell eine halbwegs gleichwertige ausgewählt, bei den Nicht-Kernkomponenten habe stehen die jeweils annehmbaren Preise ohne auf ein spezielles Produkt zu verweisen. Bei Reichelt kosten die Bauteile für einen Schaltregler 2,16 Euro, bei Farnell (inkl. MwSt.) 2,93 Euro. Trotzdem kann sich (bis auf die Spule) der Kauf bei Farnell - sofern man dort bestellen kann - durch die Preisstaffeln lohnen. =Stromlaufplan= Der Stromlaufplan ist reichlich unspektakulär, er ist nicht viel mehr als eine der Application Notes im Datenblatt. <gallery> Datei:minipsu_v1_sch.png|Stromlaufplan des Schaltreglers </gallery> =Layout= Das Layout ist da ein bisschen aufwändiger. Wie in der Einleitung angedeutet, soll es ein Ersatz für die 78xx werden. Das heißt: gleicher Formfaktor. Laut einem zufällig herausgezogenen [http://www.ti.com/lit/ds/symlink/lm340-n.pdf Datenblatt] ist das Package in im Mittel 10,16 x 14,99 mm² groß und 4,58 mm dick. Das gilt es anzustreben. Der Anschluss erfolgt, wie schon im Stromlaufplan zu sehen ist, über eine zweireihige Stiftleiste, die der Pinbelegung der gängigen Regler folgt. Der Konnektor ist allerdings nicht stehend, sondern liegend am Rand der Leiterkarte vorgesehen (demnächst in der [[EAGLE-Bibliotheken|EAGLE-Bibliothek]] verfügbar). Selbstverständlich muss man keine 6-polige Stiftleiste anlöten, es reicht eine dreipolige. Wenn überhaupt. Mit entsprechenden Pads auf der Hauptplatine kann man den Regler entweder stehend auflöten oder über eine Stiftleiste durch die Durchkontaktierungen auch liegend montieren. Möchte man sich die Stiftleiste sparen, kann man das Modul auch auf Höhe der Durchkontaktierungen absägen und an diesen liegend über die nun offengelegten Pads am Leiterkartenrand befestigen. Die Anschlussbelegung hat schon eine nicht zu unterschätzende Auswirkung auf die Platzierung der restlichen Bauteile. Gleichzeitig muss man auf allgemeine Designregeln für Schaltwandler achten - [http://www.lothar-miller.de/s9y/categories/40-Layout-Schaltregler Lothar Miller] hat hierfür einen sehr guten Artikel geschrieben. Um diesen Regeln gerecht zu werden hilf nur: Platzieren, überprüfen, neu platzieren, nochmal überprüfen und das behalten, mit dem man am wenigsten unglücklich ist. Das perfekte Design schafft man wohl nur extrem selten. Denn: wenn es in Bezug auf Strompfade gut ist, kann einem die Thermik oder die Platzierung von anderen Modulen (ok, hier nicht) in die Suppe spucken. Ich bin bei folgendem Layout angekommen: <gallery> Datei:minipsu_v1_brd.png|Layout des Schaltreglers </gallery> Außenmaße: 10,41 x 15,08 mm². Nur ein kleines bisschen oberhalb des gesteckten Ziels aber noch innerhalb der mechanischen Specs von TI ;-) Manche werden sich vielleicht fragen, warum die Ausgangsspannung über die untere Lage zum Spannungsteiler für das Feedback führt - das könnte man doch direkt an der Diode rechts oben abgreifen.... Ja, könnte man machen, aber dann wär's halt kacke. Abgesehen von dem blöden Spruch gibt es natürlich auch einen sinnvollen Grund dafür: Wo Strom fließt, fällt Spannung ab. An der Diode oben bzw. nahe an der Induktivität fließen mitunter etwas größere Ströme - wodurch sich die Messung verfälschen könnte. In der Praxis könnte man zwar probieren, ob es auch so geht, aber es gibt 1. keine Notwendigkeit dafür und 2. hat man bei anderen Designs weniger Probleme, wenn man sich gleich an vernünftiges Sensing gewöhnt. ==Betrachtung der Strompfade== Anhand der Millerschen Strompfadbilder lässt sich relativ leicht ermitteln, ob man einen groben Schnitzer im Design hat. Interessant sind die Strompfade in den drei verschiedenen Phasen des Schaltwandlers, die ich wie folgt sowohl im Stromlaufplan als auch im Layout hervorgehoben habe: * Laden: gelb * Freilauf/Leerlauf: orange * Recovery: blau <gallery> Datei:minipsu_v1_strompfad_sch.png|Strompfad im Stromlaufplan Datei:minipsu_v1_strompfad_brd.png|Strompfad im Layout </gallery> Das sieht schon ganz ok aus, wenn auch noch nicht optimal. Die Strecke links von C1 zu IC1 ist verhältnismäßig lang. Das gibt unnötige Induktivität, Widerstand und Abstrahlfläche. Dafür ist alles wichtige des Schaltwandlers auf einer Lage, was ebenfalls die Fläche klein hält. Unter der Induktivität befindet sich auf gleicher Lage Freischnitt des Kupfers. Leiterbahnen sollte man selbstverständlich soweit wie es geht fern halten. Bezüglich Aussparungen des Kupfers auf der/den anderen Lage(n) kann man streiten. Hier steht Einkopplung von Störströmen auf andere Signale oder die Massefläche und das Abblocken des Feldes (EMV) nach außen auf im Gegensatz... Hier ist noch anzumerken, dass das Layout der Leiterkarten leicht unterschiedlich zu den hier gezeigten Fotos ist. ==Aufbau== Ein paar Wochen später sind die gefertigten Leiterkarten auch [http://hobbyelektronik.org/b/2014/10/sie-sind-da/ angekommen] - ein paar Monate später wurden dann auch die Bauteile bestellt. Für die Bestückung sind etwas Feingefühl und eine dünne Lötspitze gefragt. ==Messungen== Keine Behauptungen ohne Beweise, in diesem Fall Messungen. Mit dem Labornetzteil und meinem einfachen DMM ließ sich grundlegend bestätigen: Ja, es funktioniert! Bei den festgelegten 3,3 V Ausgangsspannung fing der Regler bei etwa 3,7 V an, vernünftig zu arbeiten. Das hat zwei Gründe: Wie oben beschrieben, muss der Duty Cycle < 100 % sein, damit die Ladungspumpe zur Erzeugung der Hilfsspannung funktioniert. Nachdem der Maximum Duty Cycle bei typ. 95 % liegt, kann man ganz plump 3,7 V * 0,95 rechnen und landet bei 3,5 Volt. Dann kommt natürlich noch der R<sub>ds,on</sub> des FET und der Innenwiderstand der Induktivität sowie Schaltverluste dazu. Alles in allem: plausibel. Ein wichtiges Merkmal für den Betrieb ist natürlich der Wirkungsgrad. Dazu ermittelt man sowohl auf Ein- als auch Ausgangsseite die Leistung (indem man Strom und Spannung misst) bei bekannter Last und wendet die in der Einleitung gezeigte Formel an. Dies führt man mit verschiedenen Lasten und Eingangsspannungen durch, schmeißt die Daten in die Tabellenkalkulation und lässt es sich plotten: <gallery> Datei:minipsu_v1_wirkungsgrad_1.png|Wirkungsgrad über Last und Eingangsspannung Muster 1 Datei:minipsu_v1_wirkungsgrad_2.png|Wirkungsgrad über Last und Eingangsspannung Muster 2 </gallery> In dem Aufbau habe ich leicht abweichende Widerstandspaarungen als in der oben gezeigten Tabelle verwendet, was allerdings weitestgehend unmaßgeblich ist. Im Diagramm sieht man recht gut, dass mit 92 % der höchste Wirkungsgrad bei 5 V Eingangsspannung und einer Last von 100 mA erreicht wird. Bei den anderen Eingangsspannungen sieht es leider nicht ganz so gut aus. Zudem gibt es bei ca. 0,3 A einen leichten systematischen Einbruch (den ich auch mit einer zweiten Leiterkarte bestätigen konnte). Momentan kann ich allerdings nur mutmaßen, woher das kommt. Aus den Aufzeichnungen lässt sich auch das Verhalten die Ausgangsspannung unter Last darstellen: [[Datei:minipsu_v1_spannung_last_1.png]] Leider war die Auflösung (10 mV) relativ gering, dadurch der Treppeneffekt. Wie man sieht, ist das Verhalten durchaus hinnehmbar. ==Optimierung== Es ist noch nicht Ende Fahnenstange - aus dem Design kann man sicher mehr herauskitzeln. Die größten Kandidaten sind sicherlich die Induktivität und die Freilaufdiode, dann kommen irgendwann die Kondensatoren. Man könnte natürlich auch den IC austauschen, aber dann hat man zwangsläufig ein anderes Design. Ein weiterer Punkt wäre die Diode in der Boost-Schaltung - leckt diese zu stark, kann der FET evtl. nicht vollständig durchschalten. Da gerade keine passenden Alternativen für Induktivität und Kondensatoren herumliegen, bleiben nur noch die Dioden. Als Schaltdiode liegt noch eine [https://www.toshiba.com/taec/components2/Datasheet_Sync/200612/DST_CRS08-TDE_EN_1640.pdf CRS08 von Toshiba], für die Boost-Diode eine [http://www.vishay.com/docs/85508/bat54v.pdf BAT54] (Schottky) herum. <gallery> Datei:minipsu_v1_wirkungsgrad_CRS08.png|CRS08 als Schaltdiode Datei:minipsu_v1_wirkungsgrad_BAT54C.png|BAT54 als Boost-Diode </gallery> Die CRS08 reißt im Mittel einen 0,6 % höheren Wirkungsgrad heraus, die BAT54 0,4 %. Mal ganz abgesehen von Messungenauigkeiten oder Wiederholbarkeit... Für die eine andere Spule muss ich auf den nächsten Karton aus Sande warten, verspreche mir aber noch eine leichte Verbesserung. =Version 2= Es geht kleiner und ein bisschen besser. ==Layout== Die BAT43WS kostet unwesentlich mehr und dürfte die Performance ein kleines Stück verbessern - gleichzeitig ist sie ein gutes Stück kleiner als die die Diode in Minimelf-Gehäuse. Der Eingangs-Kondensator ist nach ist gedreht und etwas nach oben gewandert. Das erfordert zwar, dass die Versorgung über Durchkontaktierungen geführt wird, was an dieser Stelle relativ unproblematisch sein sollte. Durch das Verschieben kann sowohl die Schaltdiode als auch der IC nach unten verschoben werden. <gallery> Datei:minipsu_v2_sch.png|Stromlaufplan von Version 2 Datei:minipsu_v2_brd.png|Layout von Version 2 </gallery> Größe: 9,6 x 13,7 mm² Auf der Unterseite befindet sich nun im Silkscreen eine Tabelle für die gesetzte Spannung: 3,3 V, 5 V und ein freies Feld. Ferner gibt es für die liegende Montage auf der gegenüberliegenden Seite der Anschlüsse noch ein mit der Masse verbundenes Lötpad. ==Betrachtung der Strompfade== Neuer Anlauf: <gallery> Datei:minipsu_v2_strompfad_brd.png|Strompfad im Layout </gallery> Die Pfade sind jetzt deutlich kürzer. Die geringere Fläche dürfte mechanisch aber stärker wiegen als die der Einfluss auf die EMV... =Downloads= [[Datei:minipsu.zip]] =Weblinks= * [http://schmidt-walter-schaltnetzteile.de/smps/smps.html Dr. Schmidt-Walter - Dimensionierung von Schaltnetzteilen] * [http://powerelectronics.com/site-files/powerelectronics.com/files/archive/powerelectronics.com/mag/606PET25.pdf D. Schelle und J. Castorenoa - Buck-Converter Design Demystified] [[Kategorie:Elektronik]] [[Kategorie:Stromversorgung]] 904bfa81dda511c41860538327e2edcd5e063b2b 977 976 2015-04-01T17:42:43Z Chris 2 wikitext text/x-wiki [[Datei:Minipsu v1 foto.jpg|thumb|Mini-Schaltwandler neben einem 7805]] Die meisten elektronischen Schaltungen haben eine geregelte Stromversorgung. Früher hat man dafür oft und gerne ein Bauteil aus der 78xx-Reihe verwendet. Ganz einfach, weil sie günstig sind, zuverlässig arbeiten und wenig Außenbeschaltung benötigen. Der große Nachteil an Linearreglern allgemein ist die in vielen Anwendungsfällen eher dürftige Effizienz und noch vielmehr die notwendige Kühlung, denn: Das Produkt aus Spannungsdifferenz zwischen Ein- und Ausgang und dem Strom, der durch den Regler fließt, ist ziemlich genau die Leistung, die man wegkühlen muss. Beispiel: ein 7805-Regler wird mit 12 V versorgt und soll eine Schaltung versorgen, die 200 mA benötigt: <math>P = \left(U_{\textrm{in}}-U_{\textrm{out}}\right) \cdot I = \left(12\textrm{ V}-5\textrm{ V}\right) \cdot 0.2 \textrm{ A} = 1.4\textrm{ W}</math> Nicht weltbeltbewegend, aber immerhin. Die Effizienz von diesem Regler liegt bei <math>\eta = \frac{P_\textrm{out}}{P_\textrm{in}}= \frac{U_\textrm{out} \cdot I_\textrm{out}}{U_\textrm{in} \cdot I_\textrm{in}}</math> wobei der Eigenbedarf der meisten Linearregler vernachlässigbar gering ist (also der Unterschied zwischen I_out und I_in), somit lassen sich die Ströme einfach kürzen und die Effizienz ist rein von den Spannungen abhängig. Im Beispiel oben ergibt sich ein Wirkungsgrad von etwa 42 %. Ziemlich mies. Mit einem Abwärtswandler (auch step-down- oder buck-converter) kann man mit - im Vergleich zu Linearreglern - etwas größerem Schaltungsaufwand deutlich bessere Ergebnisse erzielen. Dabei wird der Strom "zerhackt" und über ein Speicherelement (in aller Regel eine Induktivität) geglättet. Die Ausgangsspannung hängt dabei vom Tastverhältnis des Schalters ab. Vereinfacht gesagt: je länger dieser geschlossen ist, desto mehr Energie wird vom Eingang zum Ausgang transportiert. Der Wirkungsgrad hängt bei hierbei von mehreren Faktoren ab: * Schalttransistor * Freilaufdiode * Induktivität So toll das Prinzip ist, es hat nicht nur Vorteile. Beispielsweise hat man höhere Anforderungen an das Layout und Risiken, wenn es um das Bestehen von EMV-Zulassungen geht. Schließlich leben diese Schaltungen von steilen Flanken und mitunter kurzzeitig hohen Strömen. Außerdem sieht man am Ausgang oft deutlich größere Störungen als bei Linearreglern. Hinzu kommt noch, dass Schaltwandler aufgrund ihres Aufbaus deutlich Lastspezifischer sind. Sie sind als nicht DIE Lösung für eine Stromversorgung, sondern eine mögliche Art dafür. =Der Mini-Schaltwandler (Version 1)= Ich wollte einen kleinen und halbwegs flexibel einsetzbaren Schaltwandler haben, den man statt einem 78xx verwenden kann, natürlich nicht zu teuer. In Sachen Leistung ruhig mit Abstrichen - die meisten Anwendungen benötigen selten über 0,5 A. Eingangsspannung bis 20 V sollte ok sein, gerne aber auch etwas mehr. =Bauteilauswahl= Bei der Suche bei Farnell bin ich schnell fündig geworden: Der [http://www.microchip.com/wwwproducts/devices.aspx?dDocName=en554058 MCP16301] von Microchip. Im SOT-23-6-Gehäuse ist er zwar klein, aber noch gut per Hand lötbar, der Eingangsspannungsbereich ist angenehm groß. Der Ausgangsstrom ist mit 0,6 A mehr als hinreichend und die 500 kHz Schaltfrequenz erfordern eine relativ kleine Induktivität. Der Preis ist mit etwas um einen Euro fair. Und zu guter Letzt ist er mittlerweile auch bei Reichelt verfügbar. Nach dem IC kommt die Induktivität. Abschnitt 5.6 gibt einige Hinweise zur Auswahl samt Beispiele. Für den interessanten Bereich zwischen 2,0 bis 5 V Ausgangsspannung sollen es also 10 bis 22 µH sein und ein Sättigungsstrom von mindestens 760 mA wird empfohlen. Kurz durch den Reichelt-Katalog geblättert finden sich die Fastron 1616 FPS. Da mein Ziel erst einmal 3,3 V sind, soll es die 15 µH-Variante werden, wobei es auch passende mit 22 und 33 µH gibt. Leider wird der kleine Footprint von 4,2 x 4,2 mm² durch einen etwas schlechteren ESR erkauft. Wer Platz hat, greift lieber zur 242408 oder 242418 - diese versprechen eine etwas höhere Effizienz! Fehlt noch die Schaltdiode als Kernkomponente. Diese sollte klein und schnell sein und etwa 1 A können. Bei der Spannungsfestigkeit sollten 30 V reichen - mehr kann der MCP eh nicht. Die [http://www.reichelt.de/index.html?ACTION=3&GROUPID=2991&ARTICLE=146621 SS 13L] von Taiwan Semiconductor passt. Zur Glättung empfiehlt das Datenblatt 1 µF bis 10 µF am Eingang und 10 µF bis 22 µF am Ausgang (wobei es zwischen den Application Examples und der Empfehlung in Tabelle 5-2 etwas widersprüchlich ist). Um es generisch zu halten: 10 µF am Eingang, 22 µF am Ausgang. Hat Reichelt jeweils im 1206-Package, ist aber leider nicht so ganz billig. Wer Zugriff auf Farnell hat, bekommt mehr und vermutlich auch eine günstigere Auswahl. Der Schaltwandler-IC verwendet einen n-Kanal-FET als Schalter. Da sich dieser - wie von der Topologie gefordert - auf der High-Side befinden und U<sub>GS</sub> > U<sub>th</sub> sein muss, wird eine Hilfsspannung größer als U<sub>in</sub> benötigt. Eine Schaltung mit p-Kanal-FET wäre zwar sicher einfacher, würde aber leichte Abstriche im Wirkungsgrad bedeuten (idR. höherer R<sub>ds,on</sub>). Wie dem auch sei, die Hilfsspannung bekommt man fast geschenkt, indem man den Schalttransistor und die Induktivität als Ladungspumpe verwendet. Dazu benötigt man zusätzlich lediglich eine Diode und einen Kondensator. Damit das auch funktioniert, darf der FET nie durchgängig eingeschaltet sein - sonst wird nichts mehr gepumpt und er kann nicht mehr geschaltet werden. Da die benötigte Leistung durchweg niedrig ist, reichen Wald- und Wiesenkomponenten. Wie im Datenblatt vorgeschlagen eine 1N4148 und ein 100 nF-Kerko. Fehlen noch die Feedback-Widerstände. Um das verwenden zu können, was vielleicht sogar in der Grabbelkiste liegt, empfehle ich das Tool [http://www.muellerzumhagen.de/index.php/sascha/tools/widerstand-ist-zwecklos Widerstand ist Zwecklos], das direkt ein Werkzeug zum Ermitteln von Widerständen für Spannungsregler bietet. Vref ist mit 0,8 V zu wählen. Für 3,3 V gibt es aus der E6-Reihe ein sehr gut passendes Pärchen, für 5 V muss man entweder auf die E24-Reihe ausweichen, oder 3 Widerstände verwenden: {| class="wikitable" |- ! U<sub>out,target</sub> [V] !! Reihe !! R<sub>upper</sub> [Ohm] !! R<sub>lower</sub> [Ohm] !! U<sub>out</sub> (worst case) [V] |- | 3,3 || E6 || 47 k || 15 k || 3,307 (3,249 ... 3,349) |- | 5 || E24 || 27 k || 5,1 k || 5,035 (4,942 ... 5,111) |- | 5 || E24 || 36 k || 6,8 k || 5,035 (4,939 ... 5,108) |- | 5 || E6 || 33 k p 100 k || 4,7 k || 5,0233 (4,942 ... 5,111) |- | 5 || E6 || 47 k p 150 k || 6,8 k || 5,0102 (4,930 ... 5,098) |- |} Es ergibt sich folgende BOM: {| class="wikitable" |- ! Komponente !! Menge !! Reichelt Bestellname !! Preis [€] !! Farnell Bestellnummer !! Preis [€] |- | Microchip MCP16301 || 1 || MCP 16301T-I/CHY || 1,15 || 2009288 || 1,21 |- | Fastron 1616FPS 15µH || 1 || L-1616FPS 15µ || 0,22 || 2345178* || 1,15 |- | TSC SS13L || 1 || SS 13L || 0,11 || 1559158 || 0,1 |- | 1N4148 || 1 || 1N 4148 SMD || 0,02 || 1612361 || 0,04 |- | 100nF-Kerko || 1 || X7R-G0603 100N || 0,15 || * || 0,01 |- | 10µF/25V || 1 || X7R-G1206 10/25 || 0,24 || * || 0,25 |- | 22µF/6V || 1 || X5R-G0805 22/6 || 0,07 || * || 0,15 |- | 47kOhm 0603 || 1 || SMD-0603 47K || 0,1 || * || 0,01 |- | 15kOhm 0603 || 1 || SMD-0603 15K || 0,1 || * || 0,01 |- |} Für die Induktivität habe ich bei Farnell eine halbwegs gleichwertige ausgewählt, bei den Nicht-Kernkomponenten habe stehen die jeweils annehmbaren Preise ohne auf ein spezielles Produkt zu verweisen. Bei Reichelt kosten die Bauteile für einen Schaltregler 2,16 Euro, bei Farnell (inkl. MwSt.) 2,93 Euro. Trotzdem kann sich (bis auf die Spule) der Kauf bei Farnell - sofern man dort bestellen kann - durch die Preisstaffeln lohnen. =Stromlaufplan= Der Stromlaufplan ist reichlich unspektakulär, er ist nicht viel mehr als eine der Application Notes im Datenblatt. <gallery> Datei:minipsu_v1_sch.png|Stromlaufplan des Schaltreglers </gallery> =Layout= Das Layout ist da ein bisschen aufwändiger. Wie in der Einleitung angedeutet, soll es ein Ersatz für die 78xx werden. Das heißt: gleicher Formfaktor. Laut einem zufällig herausgezogenen [http://www.ti.com/lit/ds/symlink/lm340-n.pdf Datenblatt] ist das Package in im Mittel 10,16 x 14,99 mm² groß und 4,58 mm dick. Das gilt es anzustreben. Der Anschluss erfolgt, wie schon im Stromlaufplan zu sehen ist, über eine zweireihige Stiftleiste, die der Pinbelegung der gängigen Regler folgt. Der Konnektor ist allerdings nicht stehend, sondern liegend am Rand der Leiterkarte vorgesehen (demnächst in der [[EAGLE-Bibliotheken|EAGLE-Bibliothek]] verfügbar). Selbstverständlich muss man keine 6-polige Stiftleiste anlöten, es reicht eine dreipolige. Wenn überhaupt. Mit entsprechenden Pads auf der Hauptplatine kann man den Regler entweder stehend auflöten oder über eine Stiftleiste durch die Durchkontaktierungen auch liegend montieren. Möchte man sich die Stiftleiste sparen, kann man das Modul auch auf Höhe der Durchkontaktierungen absägen und an diesen liegend über die nun offengelegten Pads am Leiterkartenrand befestigen. Die Anschlussbelegung hat schon eine nicht zu unterschätzende Auswirkung auf die Platzierung der restlichen Bauteile. Gleichzeitig muss man auf allgemeine Designregeln für Schaltwandler achten - [http://www.lothar-miller.de/s9y/categories/40-Layout-Schaltregler Lothar Miller] hat hierfür einen sehr guten Artikel geschrieben. Um diesen Regeln gerecht zu werden hilf nur: Platzieren, überprüfen, neu platzieren, nochmal überprüfen und das behalten, mit dem man am wenigsten unglücklich ist. Das perfekte Design schafft man wohl nur extrem selten. Denn: wenn es in Bezug auf Strompfade gut ist, kann einem die Thermik oder die Platzierung von anderen Modulen (ok, hier nicht) in die Suppe spucken. Ich bin bei folgendem Layout angekommen: <gallery> Datei:minipsu_v1_brd.png|Layout des Schaltreglers </gallery> Außenmaße: 10,41 x 15,08 mm². Nur ein kleines bisschen oberhalb des gesteckten Ziels aber noch innerhalb der mechanischen Specs von TI ;-) Manche werden sich vielleicht fragen, warum die Ausgangsspannung über die untere Lage zum Spannungsteiler für das Feedback führt - das könnte man doch direkt an der Diode rechts oben abgreifen.... Ja, könnte man machen, aber dann wär's halt kacke. Abgesehen von dem blöden Spruch gibt es natürlich auch einen sinnvollen Grund dafür: Wo Strom fließt, fällt Spannung ab. An der Diode oben bzw. nahe an der Induktivität fließen mitunter etwas größere Ströme - wodurch sich die Messung verfälschen könnte. In der Praxis könnte man zwar probieren, ob es auch so geht, aber es gibt 1. keine Notwendigkeit dafür und 2. hat man bei anderen Designs weniger Probleme, wenn man sich gleich an vernünftiges Sensing gewöhnt. ==Betrachtung der Strompfade== Anhand der Millerschen Strompfadbilder lässt sich relativ leicht ermitteln, ob man einen groben Schnitzer im Design hat. Interessant sind die Strompfade in den drei verschiedenen Phasen des Schaltwandlers, die ich wie folgt sowohl im Stromlaufplan als auch im Layout hervorgehoben habe: * Laden: gelb * Freilauf/Leerlauf: orange * Recovery: blau <gallery> Datei:minipsu_v1_strompfad_sch.png|Strompfad im Stromlaufplan Datei:minipsu_v1_strompfad_brd.png|Strompfad im Layout </gallery> Das sieht schon ganz ok aus, wenn auch noch nicht optimal. Die Strecke links von C1 zu IC1 ist verhältnismäßig lang. Das gibt unnötige Induktivität, Widerstand und Abstrahlfläche. Dafür ist alles wichtige des Schaltwandlers auf einer Lage, was ebenfalls die Fläche klein hält. Unter der Induktivität befindet sich auf gleicher Lage Freischnitt des Kupfers. Leiterbahnen sollte man selbstverständlich soweit wie es geht fern halten. Bezüglich Aussparungen des Kupfers auf der/den anderen Lage(n) kann man streiten. Hier steht Einkopplung von Störströmen auf andere Signale oder die Massefläche und das Abblocken des Feldes (EMV) nach außen auf im Gegensatz... Hier ist noch anzumerken, dass das Layout der Leiterkarten leicht unterschiedlich zu den hier gezeigten Fotos ist. ==Aufbau== Ein paar Wochen später sind die gefertigten Leiterkarten auch [http://hobbyelektronik.org/b/2014/10/sie-sind-da/ angekommen] - ein paar Monate später wurden dann auch die Bauteile bestellt. Für die Bestückung sind etwas Feingefühl und eine dünne Lötspitze gefragt. ==Messungen== Keine Behauptungen ohne Beweise, in diesem Fall Messungen. Mit dem Labornetzteil und meinem einfachen DMM ließ sich grundlegend bestätigen: Ja, es funktioniert! Bei den festgelegten 3,3 V Ausgangsspannung fing der Regler bei etwa 3,7 V an, vernünftig zu arbeiten. Das hat zwei Gründe: Wie oben beschrieben, muss der Duty Cycle < 100 % sein, damit die Ladungspumpe zur Erzeugung der Hilfsspannung funktioniert. Nachdem der Maximum Duty Cycle bei typ. 95 % liegt, kann man ganz plump 3,7 V * 0,95 rechnen und landet bei 3,5 Volt. Dann kommt natürlich noch der R<sub>ds,on</sub> des FET und der Innenwiderstand der Induktivität sowie Schaltverluste dazu. Alles in allem: plausibel. Ein wichtiges Merkmal für den Betrieb ist natürlich der Wirkungsgrad. Dazu ermittelt man sowohl auf Ein- als auch Ausgangsseite die Leistung (indem man Strom und Spannung misst) bei bekannter Last und wendet die in der Einleitung gezeigte Formel an. Dies führt man mit verschiedenen Lasten und Eingangsspannungen durch, schmeißt die Daten in die Tabellenkalkulation und lässt es sich plotten: <gallery> Datei:minipsu_v1_wirkungsgrad_1.png|Wirkungsgrad über Last und Eingangsspannung Muster 1 Datei:minipsu_v1_wirkungsgrad_2.png|Wirkungsgrad über Last und Eingangsspannung Muster 2 </gallery> In dem Aufbau habe ich leicht abweichende Widerstandspaarungen als in der oben gezeigten Tabelle verwendet, was allerdings weitestgehend unmaßgeblich ist. Im Diagramm sieht man recht gut, dass mit 92 % der höchste Wirkungsgrad bei 5 V Eingangsspannung und einer Last von 100 mA erreicht wird. Bei den anderen Eingangsspannungen sieht es leider nicht ganz so gut aus. Zudem gibt es bei ca. 0,3 A einen leichten systematischen Einbruch (den ich auch mit einer zweiten Leiterkarte bestätigen konnte). Momentan kann ich allerdings nur mutmaßen, woher das kommt. Aus den Aufzeichnungen lässt sich auch das Verhalten die Ausgangsspannung unter Last darstellen: [[Datei:minipsu_v1_spannung_last_1.png]] Leider war die Auflösung (10 mV) relativ gering, dadurch der Treppeneffekt. Wie man sieht, ist das Verhalten durchaus hinnehmbar. ==Optimierung== Es ist noch nicht Ende Fahnenstange - aus dem Design kann man sicher mehr herauskitzeln. Die größten Kandidaten sind sicherlich die Induktivität und die Freilaufdiode, dann kommen irgendwann die Kondensatoren. Man könnte natürlich auch den IC austauschen, aber dann hat man zwangsläufig ein anderes Design. Ein weiterer Punkt wäre die Diode in der Boost-Schaltung - leckt diese zu stark, kann der FET evtl. nicht vollständig durchschalten. Da gerade keine passenden Alternativen für Induktivität und Kondensatoren herumliegen, bleiben nur noch die Dioden. Als Schaltdiode liegt noch eine [https://www.toshiba.com/taec/components2/Datasheet_Sync/200612/DST_CRS08-TDE_EN_1640.pdf CRS08 von Toshiba], für die Boost-Diode eine [http://www.vishay.com/docs/85508/bat54v.pdf BAT54] (Schottky) herum. <gallery> Datei:minipsu_v1_wirkungsgrad_CRS08.png|CRS08 als Schaltdiode Datei:minipsu_v1_wirkungsgrad_BAT54C.png|BAT54 als Boost-Diode </gallery> Die CRS08 reißt im Mittel einen 0,6 % höheren Wirkungsgrad heraus, die BAT54 0,4 %. Mal ganz abgesehen von Messungenauigkeiten oder Wiederholbarkeit... Für die eine andere Spule muss ich auf den nächsten Karton aus Sande warten, verspreche mir aber noch eine leichte Verbesserung. =Version 2= Es geht kleiner und ein bisschen besser. ==Layout== Die BAT43WS kostet unwesentlich mehr und dürfte die Performance ein kleines Stück verbessern - gleichzeitig ist sie ein gutes Stück kleiner als die die Diode in Minimelf-Gehäuse. Der Eingangs-Kondensator ist nach ist gedreht und etwas nach oben gewandert. Das erfordert zwar, dass die Versorgung über Durchkontaktierungen geführt wird, was an dieser Stelle relativ unproblematisch sein sollte. Durch das Verschieben kann sowohl die Schaltdiode als auch der IC nach unten verschoben werden. <gallery> Datei:minipsu_v2_sch.png|Stromlaufplan von Version 2 Datei:minipsu_v2_brd.png|Layout von Version 2 </gallery> Größe: 9,6 x 13,7 mm² Auf der Unterseite befindet sich nun im Silkscreen eine Tabelle für die gesetzte Spannung: 3,3 V, 5 V und ein freies Feld. Ferner gibt es für die liegende Montage auf der gegenüberliegenden Seite der Anschlüsse noch ein mit der Masse verbundenes Lötpad. ==Betrachtung der Strompfade== Neuer Anlauf: <gallery> Datei:minipsu_v2_strompfad_brd.png|Strompfad im Layout </gallery> Die Pfade sind jetzt deutlich kürzer. Die geringere Fläche dürfte mechanisch aber stärker wiegen als die der Einfluss auf die EMV... =Downloads= [[Datei:minipsu.zip]] =Weblinks= * [http://schmidt-walter-schaltnetzteile.de/smps/smps.html Dr. Schmidt-Walter - Dimensionierung von Schaltnetzteilen] * [http://powerelectronics.com/site-files/powerelectronics.com/files/archive/powerelectronics.com/mag/606PET25.pdf D. Schelle und J. Castorenoa - Buck-Converter Design Demystified] [[Kategorie:Elektronik]] [[Kategorie:Stromversorgung]] 5a9419f5f0962ec4fb406b53c1c8ecb36d9c1cf5 978 977 2015-04-01T18:19:48Z Chris 2 Wer will? wikitext text/x-wiki [[Datei:Minipsu v1 foto.jpg|thumb|Mini-Schaltwandler neben einem 7805]] Die meisten elektronischen Schaltungen haben eine geregelte Stromversorgung. Früher hat man dafür oft und gerne ein Bauteil aus der 78xx-Reihe verwendet. Ganz einfach, weil sie günstig sind, zuverlässig arbeiten und wenig Außenbeschaltung benötigen. Der große Nachteil an Linearreglern allgemein ist die in vielen Anwendungsfällen eher dürftige Effizienz und noch vielmehr die notwendige Kühlung, denn: Das Produkt aus Spannungsdifferenz zwischen Ein- und Ausgang und dem Strom, der durch den Regler fließt, ist ziemlich genau die Leistung, die man wegkühlen muss. Beispiel: ein 7805-Regler wird mit 12 V versorgt und soll eine Schaltung versorgen, die 200 mA benötigt: <math>P = \left(U_{\textrm{in}}-U_{\textrm{out}}\right) \cdot I = \left(12\textrm{ V}-5\textrm{ V}\right) \cdot 0.2 \textrm{ A} = 1.4\textrm{ W}</math> Nicht weltbeltbewegend, aber immerhin. Die Effizienz von diesem Regler liegt bei <math>\eta = \frac{P_\textrm{out}}{P_\textrm{in}}= \frac{U_\textrm{out} \cdot I_\textrm{out}}{U_\textrm{in} \cdot I_\textrm{in}}</math> wobei der Eigenbedarf der meisten Linearregler vernachlässigbar gering ist (also der Unterschied zwischen I_out und I_in), somit lassen sich die Ströme einfach kürzen und die Effizienz ist rein von den Spannungen abhängig. Im Beispiel oben ergibt sich ein Wirkungsgrad von etwa 42 %. Ziemlich mies. Mit einem Abwärtswandler (auch step-down- oder buck-converter) kann man mit - im Vergleich zu Linearreglern - etwas größerem Schaltungsaufwand deutlich bessere Ergebnisse erzielen. Dabei wird der Strom "zerhackt" und über ein Speicherelement (in aller Regel eine Induktivität) geglättet. Die Ausgangsspannung hängt dabei vom Tastverhältnis des Schalters ab. Vereinfacht gesagt: je länger dieser geschlossen ist, desto mehr Energie wird vom Eingang zum Ausgang transportiert. Der Wirkungsgrad hängt bei hierbei von mehreren Faktoren ab: * Schalttransistor * Freilaufdiode * Induktivität So toll das Prinzip ist, es hat nicht nur Vorteile. Beispielsweise hat man höhere Anforderungen an das Layout und Risiken, wenn es um das Bestehen von EMV-Zulassungen geht. Schließlich leben diese Schaltungen von steilen Flanken und mitunter kurzzeitig hohen Strömen. Außerdem sieht man am Ausgang oft deutlich größere Störungen als bei Linearreglern. Hinzu kommt noch, dass Schaltwandler aufgrund ihres Aufbaus deutlich Lastspezifischer sind. Sie sind als nicht DIE Lösung für eine Stromversorgung, sondern eine mögliche Art dafür. =Der Mini-Schaltwandler (Version 1)= Ich wollte einen kleinen und halbwegs flexibel einsetzbaren Schaltwandler haben, den man statt einem 78xx verwenden kann, natürlich nicht zu teuer. In Sachen Leistung ruhig mit Abstrichen - die meisten Anwendungen benötigen selten über 0,5 A. Eingangsspannung bis 20 V sollte ok sein, gerne aber auch etwas mehr. =Bauteilauswahl= Bei der Suche bei Farnell bin ich schnell fündig geworden: Der [http://www.microchip.com/wwwproducts/devices.aspx?dDocName=en554058 MCP16301] von Microchip. Im SOT-23-6-Gehäuse ist er zwar klein, aber noch gut per Hand lötbar, der Eingangsspannungsbereich ist angenehm groß. Der Ausgangsstrom ist mit 0,6 A mehr als hinreichend und die 500 kHz Schaltfrequenz erfordern eine relativ kleine Induktivität. Der Preis ist mit etwas um einen Euro fair. Und zu guter Letzt ist er mittlerweile auch bei Reichelt verfügbar. Nach dem IC kommt die Induktivität. Abschnitt 5.6 gibt einige Hinweise zur Auswahl samt Beispiele. Für den interessanten Bereich zwischen 2,0 bis 5 V Ausgangsspannung sollen es also 10 bis 22 µH sein und ein Sättigungsstrom von mindestens 760 mA wird empfohlen. Kurz durch den Reichelt-Katalog geblättert finden sich die Fastron 1616 FPS. Da mein Ziel erst einmal 3,3 V sind, soll es die 15 µH-Variante werden, wobei es auch passende mit 22 und 33 µH gibt. Leider wird der kleine Footprint von 4,2 x 4,2 mm² durch einen etwas schlechteren ESR erkauft. Wer Platz hat, greift lieber zur 242408 oder 242418 - diese versprechen eine etwas höhere Effizienz! Fehlt noch die Schaltdiode als Kernkomponente. Diese sollte klein und schnell sein und etwa 1 A können. Bei der Spannungsfestigkeit sollten 30 V reichen - mehr kann der MCP eh nicht. Die [http://www.reichelt.de/index.html?ACTION=3&GROUPID=2991&ARTICLE=146621 SS 13L] von Taiwan Semiconductor passt. Zur Glättung empfiehlt das Datenblatt 1 µF bis 10 µF am Eingang und 10 µF bis 22 µF am Ausgang (wobei es zwischen den Application Examples und der Empfehlung in Tabelle 5-2 etwas widersprüchlich ist). Um es generisch zu halten: 10 µF am Eingang, 22 µF am Ausgang. Hat Reichelt jeweils im 1206-Package, ist aber leider nicht so ganz billig. Wer Zugriff auf Farnell hat, bekommt mehr und vermutlich auch eine günstigere Auswahl. Der Schaltwandler-IC verwendet einen n-Kanal-FET als Schalter. Da sich dieser - wie von der Topologie gefordert - auf der High-Side befinden und U<sub>GS</sub> > U<sub>th</sub> sein muss, wird eine Hilfsspannung größer als U<sub>in</sub> benötigt. Eine Schaltung mit p-Kanal-FET wäre zwar sicher einfacher, würde aber leichte Abstriche im Wirkungsgrad bedeuten (idR. höherer R<sub>ds,on</sub>). Wie dem auch sei, die Hilfsspannung bekommt man fast geschenkt, indem man den Schalttransistor und die Induktivität als Ladungspumpe verwendet. Dazu benötigt man zusätzlich lediglich eine Diode und einen Kondensator. Damit das auch funktioniert, darf der FET nie durchgängig eingeschaltet sein - sonst wird nichts mehr gepumpt und er kann nicht mehr geschaltet werden. Da die benötigte Leistung durchweg niedrig ist, reichen Wald- und Wiesenkomponenten. Wie im Datenblatt vorgeschlagen eine 1N4148 und ein 100 nF-Kerko. Fehlen noch die Feedback-Widerstände. Um das verwenden zu können, was vielleicht sogar in der Grabbelkiste liegt, empfehle ich das Tool [http://www.muellerzumhagen.de/index.php/sascha/tools/widerstand-ist-zwecklos Widerstand ist Zwecklos], das direkt ein Werkzeug zum Ermitteln von Widerständen für Spannungsregler bietet. Vref ist mit 0,8 V zu wählen. Für 3,3 V gibt es aus der E6-Reihe ein sehr gut passendes Pärchen, für 5 V muss man entweder auf die E24-Reihe ausweichen, oder 3 Widerstände verwenden: {| class="wikitable" |- ! U<sub>out,target</sub> [V] !! Reihe !! R<sub>upper</sub> [Ohm] !! R<sub>lower</sub> [Ohm] !! U<sub>out</sub> (worst case) [V] |- | 3,3 || E6 || 47 k || 15 k || 3,307 (3,249 ... 3,349) |- | 5 || E24 || 27 k || 5,1 k || 5,035 (4,942 ... 5,111) |- | 5 || E24 || 36 k || 6,8 k || 5,035 (4,939 ... 5,108) |- | 5 || E6 || 33 k p 100 k || 4,7 k || 5,0233 (4,942 ... 5,111) |- | 5 || E6 || 47 k p 150 k || 6,8 k || 5,0102 (4,930 ... 5,098) |- |} Es ergibt sich folgende BOM: {| class="wikitable" |- ! Komponente !! Menge !! Reichelt Bestellname !! Preis [€] !! Farnell Bestellnummer !! Preis [€] |- | Microchip MCP16301 || 1 || MCP 16301T-I/CHY || 1,15 || 2009288 || 1,21 |- | Fastron 1616FPS 15µH || 1 || L-1616FPS 15µ || 0,22 || 2345178* || 1,15 |- | TSC SS13L || 1 || SS 13L || 0,11 || 1559158 || 0,1 |- | 1N4148 || 1 || 1N 4148 SMD || 0,02 || 1612361 || 0,04 |- | 100nF-Kerko || 1 || X7R-G0603 100N || 0,15 || * || 0,01 |- | 10µF/25V || 1 || X7R-G1206 10/25 || 0,24 || * || 0,25 |- | 22µF/6V || 1 || X5R-G0805 22/6 || 0,07 || * || 0,15 |- | 47kOhm 0603 || 1 || SMD-0603 47K || 0,1 || * || 0,01 |- | 15kOhm 0603 || 1 || SMD-0603 15K || 0,1 || * || 0,01 |- |} Für die Induktivität habe ich bei Farnell eine halbwegs gleichwertige ausgewählt, bei den Nicht-Kernkomponenten habe stehen die jeweils annehmbaren Preise ohne auf ein spezielles Produkt zu verweisen. Bei Reichelt kosten die Bauteile für einen Schaltregler 2,16 Euro, bei Farnell (inkl. MwSt.) 2,93 Euro. Trotzdem kann sich (bis auf die Spule) der Kauf bei Farnell - sofern man dort bestellen kann - durch die Preisstaffeln lohnen. =Stromlaufplan= Der Stromlaufplan ist reichlich unspektakulär, er ist nicht viel mehr als eine der Application Notes im Datenblatt. <gallery> Datei:minipsu_v1_sch.png|Stromlaufplan des Schaltreglers </gallery> =Layout= Das Layout ist da ein bisschen aufwändiger. Wie in der Einleitung angedeutet, soll es ein Ersatz für die 78xx werden. Das heißt: gleicher Formfaktor. Laut einem zufällig herausgezogenen [http://www.ti.com/lit/ds/symlink/lm340-n.pdf Datenblatt] ist das Package in im Mittel 10,16 x 14,99 mm² groß und 4,58 mm dick. Das gilt es anzustreben. Der Anschluss erfolgt, wie schon im Stromlaufplan zu sehen ist, über eine zweireihige Stiftleiste, die der Pinbelegung der gängigen Regler folgt. Der Konnektor ist allerdings nicht stehend, sondern liegend am Rand der Leiterkarte vorgesehen (demnächst in der [[EAGLE-Bibliotheken|EAGLE-Bibliothek]] verfügbar). Selbstverständlich muss man keine 6-polige Stiftleiste anlöten, es reicht eine dreipolige. Wenn überhaupt. Mit entsprechenden Pads auf der Hauptplatine kann man den Regler entweder stehend auflöten oder über eine Stiftleiste durch die Durchkontaktierungen auch liegend montieren. Möchte man sich die Stiftleiste sparen, kann man das Modul auch auf Höhe der Durchkontaktierungen absägen und an diesen liegend über die nun offengelegten Pads am Leiterkartenrand befestigen. Die Anschlussbelegung hat schon eine nicht zu unterschätzende Auswirkung auf die Platzierung der restlichen Bauteile. Gleichzeitig muss man auf allgemeine Designregeln für Schaltwandler achten - [http://www.lothar-miller.de/s9y/categories/40-Layout-Schaltregler Lothar Miller] hat hierfür einen sehr guten Artikel geschrieben. Um diesen Regeln gerecht zu werden hilf nur: Platzieren, überprüfen, neu platzieren, nochmal überprüfen und das behalten, mit dem man am wenigsten unglücklich ist. Das perfekte Design schafft man wohl nur extrem selten. Denn: wenn es in Bezug auf Strompfade gut ist, kann einem die Thermik oder die Platzierung von anderen Modulen (ok, hier nicht) in die Suppe spucken. Ich bin bei folgendem Layout angekommen: <gallery> Datei:minipsu_v1_brd.png|Layout des Schaltreglers </gallery> Außenmaße: 10,41 x 15,08 mm². Nur ein kleines bisschen oberhalb des gesteckten Ziels aber noch innerhalb der mechanischen Specs von TI ;-) Manche werden sich vielleicht fragen, warum die Ausgangsspannung über die untere Lage zum Spannungsteiler für das Feedback führt - das könnte man doch direkt an der Diode rechts oben abgreifen.... Ja, könnte man machen, aber dann wär's halt kacke. Abgesehen von dem blöden Spruch gibt es natürlich auch einen sinnvollen Grund dafür: Wo Strom fließt, fällt Spannung ab. An der Diode oben bzw. nahe an der Induktivität fließen mitunter etwas größere Ströme - wodurch sich die Messung verfälschen könnte. In der Praxis könnte man zwar probieren, ob es auch so geht, aber es gibt 1. keine Notwendigkeit dafür und 2. hat man bei anderen Designs weniger Probleme, wenn man sich gleich an vernünftiges Sensing gewöhnt. ==Betrachtung der Strompfade== Anhand der Millerschen Strompfadbilder lässt sich relativ leicht ermitteln, ob man einen groben Schnitzer im Design hat. Interessant sind die Strompfade in den drei verschiedenen Phasen des Schaltwandlers, die ich wie folgt sowohl im Stromlaufplan als auch im Layout hervorgehoben habe: * Laden: gelb * Freilauf/Leerlauf: orange * Recovery: blau <gallery> Datei:minipsu_v1_strompfad_sch.png|Strompfad im Stromlaufplan Datei:minipsu_v1_strompfad_brd.png|Strompfad im Layout </gallery> Das sieht schon ganz ok aus, wenn auch noch nicht optimal. Die Strecke links von C1 zu IC1 ist verhältnismäßig lang. Das gibt unnötige Induktivität, Widerstand und Abstrahlfläche. Dafür ist alles wichtige des Schaltwandlers auf einer Lage, was ebenfalls die Fläche klein hält. Unter der Induktivität befindet sich auf gleicher Lage Freischnitt des Kupfers. Leiterbahnen sollte man selbstverständlich soweit wie es geht fern halten. Bezüglich Aussparungen des Kupfers auf der/den anderen Lage(n) kann man streiten. Hier steht Einkopplung von Störströmen auf andere Signale oder die Massefläche und das Abblocken des Feldes (EMV) nach außen auf im Gegensatz... Hier ist noch anzumerken, dass das Layout der Leiterkarten leicht unterschiedlich zu den hier gezeigten Fotos ist. ==Aufbau== Ein paar Wochen später sind die gefertigten Leiterkarten auch [http://hobbyelektronik.org/b/2014/10/sie-sind-da/ angekommen] - ein paar Monate später wurden dann auch die Bauteile bestellt. Für die Bestückung sind etwas Feingefühl und eine dünne Lötspitze gefragt. ==Messungen== Keine Behauptungen ohne Beweise, in diesem Fall Messungen. Mit dem Labornetzteil und meinem einfachen DMM ließ sich grundlegend bestätigen: Ja, es funktioniert! Bei den festgelegten 3,3 V Ausgangsspannung fing der Regler bei etwa 3,7 V an, vernünftig zu arbeiten. Das hat zwei Gründe: Wie oben beschrieben, muss der Duty Cycle < 100 % sein, damit die Ladungspumpe zur Erzeugung der Hilfsspannung funktioniert. Nachdem der Maximum Duty Cycle bei typ. 95 % liegt, kann man ganz plump 3,7 V * 0,95 rechnen und landet bei 3,5 Volt. Dann kommt natürlich noch der R<sub>ds,on</sub> des FET und der Innenwiderstand der Induktivität sowie Schaltverluste dazu. Alles in allem: plausibel. Ein wichtiges Merkmal für den Betrieb ist natürlich der Wirkungsgrad. Dazu ermittelt man sowohl auf Ein- als auch Ausgangsseite die Leistung (indem man Strom und Spannung misst) bei bekannter Last und wendet die in der Einleitung gezeigte Formel an. Dies führt man mit verschiedenen Lasten und Eingangsspannungen durch, schmeißt die Daten in die Tabellenkalkulation und lässt es sich plotten: <gallery> Datei:minipsu_v1_wirkungsgrad_1.png|Wirkungsgrad über Last und Eingangsspannung Muster 1 Datei:minipsu_v1_wirkungsgrad_2.png|Wirkungsgrad über Last und Eingangsspannung Muster 2 </gallery> In dem Aufbau habe ich leicht abweichende Widerstandspaarungen als in der oben gezeigten Tabelle verwendet, was allerdings weitestgehend unmaßgeblich ist. Im Diagramm sieht man recht gut, dass mit 92 % der höchste Wirkungsgrad bei 5 V Eingangsspannung und einer Last von 100 mA erreicht wird. Bei den anderen Eingangsspannungen sieht es leider nicht ganz so gut aus. Zudem gibt es bei ca. 0,3 A einen leichten systematischen Einbruch (den ich auch mit einer zweiten Leiterkarte bestätigen konnte). Momentan kann ich allerdings nur mutmaßen, woher das kommt. Aus den Aufzeichnungen lässt sich auch das Verhalten die Ausgangsspannung unter Last darstellen: [[Datei:minipsu_v1_spannung_last_1.png]] Leider war die Auflösung (10 mV) relativ gering, dadurch der Treppeneffekt. Wie man sieht, ist das Verhalten durchaus hinnehmbar. ==Optimierung== Es ist noch nicht Ende Fahnenstange - aus dem Design kann man sicher mehr herauskitzeln. Die größten Kandidaten sind sicherlich die Induktivität und die Freilaufdiode, dann kommen irgendwann die Kondensatoren. Man könnte natürlich auch den IC austauschen, aber dann hat man zwangsläufig ein anderes Design. Ein weiterer Punkt wäre die Diode in der Boost-Schaltung - leckt diese zu stark, kann der FET evtl. nicht vollständig durchschalten. Da gerade keine passenden Alternativen für Induktivität und Kondensatoren herumliegen, bleiben nur noch die Dioden. Als Schaltdiode liegt noch eine [https://www.toshiba.com/taec/components2/Datasheet_Sync/200612/DST_CRS08-TDE_EN_1640.pdf CRS08 von Toshiba], für die Boost-Diode eine [http://www.vishay.com/docs/85508/bat54v.pdf BAT54] (Schottky) herum. <gallery> Datei:minipsu_v1_wirkungsgrad_CRS08.png|CRS08 als Schaltdiode Datei:minipsu_v1_wirkungsgrad_BAT54C.png|BAT54 als Boost-Diode </gallery> Die CRS08 reißt im Mittel einen 0,6 % höheren Wirkungsgrad heraus, die BAT54 0,4 %. Mal ganz abgesehen von Messungenauigkeiten oder Wiederholbarkeit... Für die eine andere Spule muss ich auf den nächsten Karton aus Sande warten, verspreche mir aber noch eine leichte Verbesserung. =Version 2= Es geht kleiner und ein bisschen besser. ==Layout== Die BAT43WS kostet unwesentlich mehr und dürfte die Performance ein kleines Stück verbessern - gleichzeitig ist sie ein gutes Stück kleiner als die die Diode in Minimelf-Gehäuse. Der Eingangs-Kondensator ist nach ist gedreht und etwas nach oben gewandert. Das erfordert zwar, dass die Versorgung über Durchkontaktierungen geführt wird, was an dieser Stelle relativ unproblematisch sein sollte. Durch das Verschieben kann sowohl die Schaltdiode als auch der IC nach unten verschoben werden. <gallery> Datei:minipsu_v2_sch.png|Stromlaufplan von Version 2 Datei:minipsu_v2_brd.png|Layout von Version 2 </gallery> Größe: 9,6 x 13,7 mm² Auf der Unterseite befindet sich nun im Silkscreen eine Tabelle für die gesetzte Spannung: 3,3 V, 5 V und ein freies Feld. Ferner gibt es für die liegende Montage auf der gegenüberliegenden Seite der Anschlüsse noch ein mit der Masse verbundenes Lötpad. ==Betrachtung der Strompfade== Neuer Anlauf: <gallery> Datei:minipsu_v2_strompfad_brd.png|Strompfad im Layout </gallery> Die Pfade sind jetzt deutlich kürzer. Die geringere Fläche dürfte mechanisch aber stärker wiegen als die der Einfluss auf die EMV... =Wer will?= Ich habe noch ein paar Platinchen herumliegen. Wer will kann ein paar (gegen Versandkosten) haben. =Downloads= [[Datei:minipsu.zip]] =Weblinks= * [http://schmidt-walter-schaltnetzteile.de/smps/smps.html Dr. Schmidt-Walter - Dimensionierung von Schaltnetzteilen] * [http://powerelectronics.com/site-files/powerelectronics.com/files/archive/powerelectronics.com/mag/606PET25.pdf D. Schelle und J. Castorenoa - Buck-Converter Design Demystified] [[Kategorie:Elektronik]] [[Kategorie:Stromversorgung]] 39b5a62226bbc5b0f30be8e0503cee8842caf886 979 978 2015-04-01T18:20:40Z Chris 2 Struktur angepasst wikitext text/x-wiki [[Datei:Minipsu v1 foto.jpg|thumb|Mini-Schaltwandler neben einem 7805]] Die meisten elektronischen Schaltungen haben eine geregelte Stromversorgung. Früher hat man dafür oft und gerne ein Bauteil aus der 78xx-Reihe verwendet. Ganz einfach, weil sie günstig sind, zuverlässig arbeiten und wenig Außenbeschaltung benötigen. Der große Nachteil an Linearreglern allgemein ist die in vielen Anwendungsfällen eher dürftige Effizienz und noch vielmehr die notwendige Kühlung, denn: Das Produkt aus Spannungsdifferenz zwischen Ein- und Ausgang und dem Strom, der durch den Regler fließt, ist ziemlich genau die Leistung, die man wegkühlen muss. Beispiel: ein 7805-Regler wird mit 12 V versorgt und soll eine Schaltung versorgen, die 200 mA benötigt: <math>P = \left(U_{\textrm{in}}-U_{\textrm{out}}\right) \cdot I = \left(12\textrm{ V}-5\textrm{ V}\right) \cdot 0.2 \textrm{ A} = 1.4\textrm{ W}</math> Nicht weltbeltbewegend, aber immerhin. Die Effizienz von diesem Regler liegt bei <math>\eta = \frac{P_\textrm{out}}{P_\textrm{in}}= \frac{U_\textrm{out} \cdot I_\textrm{out}}{U_\textrm{in} \cdot I_\textrm{in}}</math> wobei der Eigenbedarf der meisten Linearregler vernachlässigbar gering ist (also der Unterschied zwischen I_out und I_in), somit lassen sich die Ströme einfach kürzen und die Effizienz ist rein von den Spannungen abhängig. Im Beispiel oben ergibt sich ein Wirkungsgrad von etwa 42 %. Ziemlich mies. Mit einem Abwärtswandler (auch step-down- oder buck-converter) kann man mit - im Vergleich zu Linearreglern - etwas größerem Schaltungsaufwand deutlich bessere Ergebnisse erzielen. Dabei wird der Strom "zerhackt" und über ein Speicherelement (in aller Regel eine Induktivität) geglättet. Die Ausgangsspannung hängt dabei vom Tastverhältnis des Schalters ab. Vereinfacht gesagt: je länger dieser geschlossen ist, desto mehr Energie wird vom Eingang zum Ausgang transportiert. Der Wirkungsgrad hängt bei hierbei von mehreren Faktoren ab: * Schalttransistor * Freilaufdiode * Induktivität So toll das Prinzip ist, es hat nicht nur Vorteile. Beispielsweise hat man höhere Anforderungen an das Layout und Risiken, wenn es um das Bestehen von EMV-Zulassungen geht. Schließlich leben diese Schaltungen von steilen Flanken und mitunter kurzzeitig hohen Strömen. Außerdem sieht man am Ausgang oft deutlich größere Störungen als bei Linearreglern. Hinzu kommt noch, dass Schaltwandler aufgrund ihres Aufbaus deutlich Lastspezifischer sind. Sie sind als nicht DIE Lösung für eine Stromversorgung, sondern eine mögliche Art dafür. =Der Mini-Schaltwandler (Version 1)= Ich wollte einen kleinen und halbwegs flexibel einsetzbaren Schaltwandler haben, den man statt einem 78xx verwenden kann, natürlich nicht zu teuer. In Sachen Leistung ruhig mit Abstrichen - die meisten Anwendungen benötigen selten über 0,5 A. Eingangsspannung bis 20 V sollte ok sein, gerne aber auch etwas mehr. ==Bauteilauswahl== Bei der Suche bei Farnell bin ich schnell fündig geworden: Der [http://www.microchip.com/wwwproducts/devices.aspx?dDocName=en554058 MCP16301] von Microchip. Im SOT-23-6-Gehäuse ist er zwar klein, aber noch gut per Hand lötbar, der Eingangsspannungsbereich ist angenehm groß. Der Ausgangsstrom ist mit 0,6 A mehr als hinreichend und die 500 kHz Schaltfrequenz erfordern eine relativ kleine Induktivität. Der Preis ist mit etwas um einen Euro fair. Und zu guter Letzt ist er mittlerweile auch bei Reichelt verfügbar. Nach dem IC kommt die Induktivität. Abschnitt 5.6 gibt einige Hinweise zur Auswahl samt Beispiele. Für den interessanten Bereich zwischen 2,0 bis 5 V Ausgangsspannung sollen es also 10 bis 22 µH sein und ein Sättigungsstrom von mindestens 760 mA wird empfohlen. Kurz durch den Reichelt-Katalog geblättert finden sich die Fastron 1616 FPS. Da mein Ziel erst einmal 3,3 V sind, soll es die 15 µH-Variante werden, wobei es auch passende mit 22 und 33 µH gibt. Leider wird der kleine Footprint von 4,2 x 4,2 mm² durch einen etwas schlechteren ESR erkauft. Wer Platz hat, greift lieber zur 242408 oder 242418 - diese versprechen eine etwas höhere Effizienz! Fehlt noch die Schaltdiode als Kernkomponente. Diese sollte klein und schnell sein und etwa 1 A können. Bei der Spannungsfestigkeit sollten 30 V reichen - mehr kann der MCP eh nicht. Die [http://www.reichelt.de/index.html?ACTION=3&GROUPID=2991&ARTICLE=146621 SS 13L] von Taiwan Semiconductor passt. Zur Glättung empfiehlt das Datenblatt 1 µF bis 10 µF am Eingang und 10 µF bis 22 µF am Ausgang (wobei es zwischen den Application Examples und der Empfehlung in Tabelle 5-2 etwas widersprüchlich ist). Um es generisch zu halten: 10 µF am Eingang, 22 µF am Ausgang. Hat Reichelt jeweils im 1206-Package, ist aber leider nicht so ganz billig. Wer Zugriff auf Farnell hat, bekommt mehr und vermutlich auch eine günstigere Auswahl. Der Schaltwandler-IC verwendet einen n-Kanal-FET als Schalter. Da sich dieser - wie von der Topologie gefordert - auf der High-Side befinden und U<sub>GS</sub> > U<sub>th</sub> sein muss, wird eine Hilfsspannung größer als U<sub>in</sub> benötigt. Eine Schaltung mit p-Kanal-FET wäre zwar sicher einfacher, würde aber leichte Abstriche im Wirkungsgrad bedeuten (idR. höherer R<sub>ds,on</sub>). Wie dem auch sei, die Hilfsspannung bekommt man fast geschenkt, indem man den Schalttransistor und die Induktivität als Ladungspumpe verwendet. Dazu benötigt man zusätzlich lediglich eine Diode und einen Kondensator. Damit das auch funktioniert, darf der FET nie durchgängig eingeschaltet sein - sonst wird nichts mehr gepumpt und er kann nicht mehr geschaltet werden. Da die benötigte Leistung durchweg niedrig ist, reichen Wald- und Wiesenkomponenten. Wie im Datenblatt vorgeschlagen eine 1N4148 und ein 100 nF-Kerko. Fehlen noch die Feedback-Widerstände. Um das verwenden zu können, was vielleicht sogar in der Grabbelkiste liegt, empfehle ich das Tool [http://www.muellerzumhagen.de/index.php/sascha/tools/widerstand-ist-zwecklos Widerstand ist Zwecklos], das direkt ein Werkzeug zum Ermitteln von Widerständen für Spannungsregler bietet. Vref ist mit 0,8 V zu wählen. Für 3,3 V gibt es aus der E6-Reihe ein sehr gut passendes Pärchen, für 5 V muss man entweder auf die E24-Reihe ausweichen, oder 3 Widerstände verwenden: {| class="wikitable" |- ! U<sub>out,target</sub> [V] !! Reihe !! R<sub>upper</sub> [Ohm] !! R<sub>lower</sub> [Ohm] !! U<sub>out</sub> (worst case) [V] |- | 3,3 || E6 || 47 k || 15 k || 3,307 (3,249 ... 3,349) |- | 5 || E24 || 27 k || 5,1 k || 5,035 (4,942 ... 5,111) |- | 5 || E24 || 36 k || 6,8 k || 5,035 (4,939 ... 5,108) |- | 5 || E6 || 33 k p 100 k || 4,7 k || 5,0233 (4,942 ... 5,111) |- | 5 || E6 || 47 k p 150 k || 6,8 k || 5,0102 (4,930 ... 5,098) |- |} Es ergibt sich folgende BOM: {| class="wikitable" |- ! Komponente !! Menge !! Reichelt Bestellname !! Preis [€] !! Farnell Bestellnummer !! Preis [€] |- | Microchip MCP16301 || 1 || MCP 16301T-I/CHY || 1,15 || 2009288 || 1,21 |- | Fastron 1616FPS 15µH || 1 || L-1616FPS 15µ || 0,22 || 2345178* || 1,15 |- | TSC SS13L || 1 || SS 13L || 0,11 || 1559158 || 0,1 |- | 1N4148 || 1 || 1N 4148 SMD || 0,02 || 1612361 || 0,04 |- | 100nF-Kerko || 1 || X7R-G0603 100N || 0,15 || * || 0,01 |- | 10µF/25V || 1 || X7R-G1206 10/25 || 0,24 || * || 0,25 |- | 22µF/6V || 1 || X5R-G0805 22/6 || 0,07 || * || 0,15 |- | 47kOhm 0603 || 1 || SMD-0603 47K || 0,1 || * || 0,01 |- | 15kOhm 0603 || 1 || SMD-0603 15K || 0,1 || * || 0,01 |- |} Für die Induktivität habe ich bei Farnell eine halbwegs gleichwertige ausgewählt, bei den Nicht-Kernkomponenten habe stehen die jeweils annehmbaren Preise ohne auf ein spezielles Produkt zu verweisen. Bei Reichelt kosten die Bauteile für einen Schaltregler 2,16 Euro, bei Farnell (inkl. MwSt.) 2,93 Euro. Trotzdem kann sich (bis auf die Spule) der Kauf bei Farnell - sofern man dort bestellen kann - durch die Preisstaffeln lohnen. ==Stromlaufplan== Der Stromlaufplan ist reichlich unspektakulär, er ist nicht viel mehr als eine der Application Notes im Datenblatt. <gallery> Datei:minipsu_v1_sch.png|Stromlaufplan des Schaltreglers </gallery> ==Layout== Das Layout ist da ein bisschen aufwändiger. Wie in der Einleitung angedeutet, soll es ein Ersatz für die 78xx werden. Das heißt: gleicher Formfaktor. Laut einem zufällig herausgezogenen [http://www.ti.com/lit/ds/symlink/lm340-n.pdf Datenblatt] ist das Package in im Mittel 10,16 x 14,99 mm² groß und 4,58 mm dick. Das gilt es anzustreben. Der Anschluss erfolgt, wie schon im Stromlaufplan zu sehen ist, über eine zweireihige Stiftleiste, die der Pinbelegung der gängigen Regler folgt. Der Konnektor ist allerdings nicht stehend, sondern liegend am Rand der Leiterkarte vorgesehen (demnächst in der [[EAGLE-Bibliotheken|EAGLE-Bibliothek]] verfügbar). Selbstverständlich muss man keine 6-polige Stiftleiste anlöten, es reicht eine dreipolige. Wenn überhaupt. Mit entsprechenden Pads auf der Hauptplatine kann man den Regler entweder stehend auflöten oder über eine Stiftleiste durch die Durchkontaktierungen auch liegend montieren. Möchte man sich die Stiftleiste sparen, kann man das Modul auch auf Höhe der Durchkontaktierungen absägen und an diesen liegend über die nun offengelegten Pads am Leiterkartenrand befestigen. Die Anschlussbelegung hat schon eine nicht zu unterschätzende Auswirkung auf die Platzierung der restlichen Bauteile. Gleichzeitig muss man auf allgemeine Designregeln für Schaltwandler achten - [http://www.lothar-miller.de/s9y/categories/40-Layout-Schaltregler Lothar Miller] hat hierfür einen sehr guten Artikel geschrieben. Um diesen Regeln gerecht zu werden hilf nur: Platzieren, überprüfen, neu platzieren, nochmal überprüfen und das behalten, mit dem man am wenigsten unglücklich ist. Das perfekte Design schafft man wohl nur extrem selten. Denn: wenn es in Bezug auf Strompfade gut ist, kann einem die Thermik oder die Platzierung von anderen Modulen (ok, hier nicht) in die Suppe spucken. Ich bin bei folgendem Layout angekommen: <gallery> Datei:minipsu_v1_brd.png|Layout des Schaltreglers </gallery> Außenmaße: 10,41 x 15,08 mm². Nur ein kleines bisschen oberhalb des gesteckten Ziels aber noch innerhalb der mechanischen Specs von TI ;-) Manche werden sich vielleicht fragen, warum die Ausgangsspannung über die untere Lage zum Spannungsteiler für das Feedback führt - das könnte man doch direkt an der Diode rechts oben abgreifen.... Ja, könnte man machen, aber dann wär's halt kacke. Abgesehen von dem blöden Spruch gibt es natürlich auch einen sinnvollen Grund dafür: Wo Strom fließt, fällt Spannung ab. An der Diode oben bzw. nahe an der Induktivität fließen mitunter etwas größere Ströme - wodurch sich die Messung verfälschen könnte. In der Praxis könnte man zwar probieren, ob es auch so geht, aber es gibt 1. keine Notwendigkeit dafür und 2. hat man bei anderen Designs weniger Probleme, wenn man sich gleich an vernünftiges Sensing gewöhnt. ==Betrachtung der Strompfade== Anhand der Millerschen Strompfadbilder lässt sich relativ leicht ermitteln, ob man einen groben Schnitzer im Design hat. Interessant sind die Strompfade in den drei verschiedenen Phasen des Schaltwandlers, die ich wie folgt sowohl im Stromlaufplan als auch im Layout hervorgehoben habe: * Laden: gelb * Freilauf/Leerlauf: orange * Recovery: blau <gallery> Datei:minipsu_v1_strompfad_sch.png|Strompfad im Stromlaufplan Datei:minipsu_v1_strompfad_brd.png|Strompfad im Layout </gallery> Das sieht schon ganz ok aus, wenn auch noch nicht optimal. Die Strecke links von C1 zu IC1 ist verhältnismäßig lang. Das gibt unnötige Induktivität, Widerstand und Abstrahlfläche. Dafür ist alles wichtige des Schaltwandlers auf einer Lage, was ebenfalls die Fläche klein hält. Unter der Induktivität befindet sich auf gleicher Lage Freischnitt des Kupfers. Leiterbahnen sollte man selbstverständlich soweit wie es geht fern halten. Bezüglich Aussparungen des Kupfers auf der/den anderen Lage(n) kann man streiten. Hier steht Einkopplung von Störströmen auf andere Signale oder die Massefläche und das Abblocken des Feldes (EMV) nach außen auf im Gegensatz... Hier ist noch anzumerken, dass das Layout der Leiterkarten leicht unterschiedlich zu den hier gezeigten Fotos ist. ==Aufbau== Ein paar Wochen später sind die gefertigten Leiterkarten auch [http://hobbyelektronik.org/b/2014/10/sie-sind-da/ angekommen] - ein paar Monate später wurden dann auch die Bauteile bestellt. Für die Bestückung sind etwas Feingefühl und eine dünne Lötspitze gefragt. ==Messungen== Keine Behauptungen ohne Beweise, in diesem Fall Messungen. Mit dem Labornetzteil und meinem einfachen DMM ließ sich grundlegend bestätigen: Ja, es funktioniert! Bei den festgelegten 3,3 V Ausgangsspannung fing der Regler bei etwa 3,7 V an, vernünftig zu arbeiten. Das hat zwei Gründe: Wie oben beschrieben, muss der Duty Cycle < 100 % sein, damit die Ladungspumpe zur Erzeugung der Hilfsspannung funktioniert. Nachdem der Maximum Duty Cycle bei typ. 95 % liegt, kann man ganz plump 3,7 V * 0,95 rechnen und landet bei 3,5 Volt. Dann kommt natürlich noch der R<sub>ds,on</sub> des FET und der Innenwiderstand der Induktivität sowie Schaltverluste dazu. Alles in allem: plausibel. Ein wichtiges Merkmal für den Betrieb ist natürlich der Wirkungsgrad. Dazu ermittelt man sowohl auf Ein- als auch Ausgangsseite die Leistung (indem man Strom und Spannung misst) bei bekannter Last und wendet die in der Einleitung gezeigte Formel an. Dies führt man mit verschiedenen Lasten und Eingangsspannungen durch, schmeißt die Daten in die Tabellenkalkulation und lässt es sich plotten: <gallery> Datei:minipsu_v1_wirkungsgrad_1.png|Wirkungsgrad über Last und Eingangsspannung Muster 1 Datei:minipsu_v1_wirkungsgrad_2.png|Wirkungsgrad über Last und Eingangsspannung Muster 2 </gallery> In dem Aufbau habe ich leicht abweichende Widerstandspaarungen als in der oben gezeigten Tabelle verwendet, was allerdings weitestgehend unmaßgeblich ist. Im Diagramm sieht man recht gut, dass mit 92 % der höchste Wirkungsgrad bei 5 V Eingangsspannung und einer Last von 100 mA erreicht wird. Bei den anderen Eingangsspannungen sieht es leider nicht ganz so gut aus. Zudem gibt es bei ca. 0,3 A einen leichten systematischen Einbruch (den ich auch mit einer zweiten Leiterkarte bestätigen konnte). Momentan kann ich allerdings nur mutmaßen, woher das kommt. Aus den Aufzeichnungen lässt sich auch das Verhalten die Ausgangsspannung unter Last darstellen: [[Datei:minipsu_v1_spannung_last_1.png]] Leider war die Auflösung (10 mV) relativ gering, dadurch der Treppeneffekt. Wie man sieht, ist das Verhalten durchaus hinnehmbar. ==Optimierung== Es ist noch nicht Ende Fahnenstange - aus dem Design kann man sicher mehr herauskitzeln. Die größten Kandidaten sind sicherlich die Induktivität und die Freilaufdiode, dann kommen irgendwann die Kondensatoren. Man könnte natürlich auch den IC austauschen, aber dann hat man zwangsläufig ein anderes Design. Ein weiterer Punkt wäre die Diode in der Boost-Schaltung - leckt diese zu stark, kann der FET evtl. nicht vollständig durchschalten. Da gerade keine passenden Alternativen für Induktivität und Kondensatoren herumliegen, bleiben nur noch die Dioden. Als Schaltdiode liegt noch eine [https://www.toshiba.com/taec/components2/Datasheet_Sync/200612/DST_CRS08-TDE_EN_1640.pdf CRS08 von Toshiba], für die Boost-Diode eine [http://www.vishay.com/docs/85508/bat54v.pdf BAT54] (Schottky) herum. <gallery> Datei:minipsu_v1_wirkungsgrad_CRS08.png|CRS08 als Schaltdiode Datei:minipsu_v1_wirkungsgrad_BAT54C.png|BAT54 als Boost-Diode </gallery> Die CRS08 reißt im Mittel einen 0,6 % höheren Wirkungsgrad heraus, die BAT54 0,4 %. Mal ganz abgesehen von Messungenauigkeiten oder Wiederholbarkeit... Für die eine andere Spule muss ich auf den nächsten Karton aus Sande warten, verspreche mir aber noch eine leichte Verbesserung. =Version 2= Es geht kleiner und ein bisschen besser. ==Layout== Die BAT43WS kostet unwesentlich mehr und dürfte die Performance ein kleines Stück verbessern - gleichzeitig ist sie ein gutes Stück kleiner als die die Diode in Minimelf-Gehäuse. Der Eingangs-Kondensator ist nach ist gedreht und etwas nach oben gewandert. Das erfordert zwar, dass die Versorgung über Durchkontaktierungen geführt wird, was an dieser Stelle relativ unproblematisch sein sollte. Durch das Verschieben kann sowohl die Schaltdiode als auch der IC nach unten verschoben werden. <gallery> Datei:minipsu_v2_sch.png|Stromlaufplan von Version 2 Datei:minipsu_v2_brd.png|Layout von Version 2 </gallery> Größe: 9,6 x 13,7 mm² Auf der Unterseite befindet sich nun im Silkscreen eine Tabelle für die gesetzte Spannung: 3,3 V, 5 V und ein freies Feld. Ferner gibt es für die liegende Montage auf der gegenüberliegenden Seite der Anschlüsse noch ein mit der Masse verbundenes Lötpad. ==Betrachtung der Strompfade== Neuer Anlauf: <gallery> Datei:minipsu_v2_strompfad_brd.png|Strompfad im Layout </gallery> Die Pfade sind jetzt deutlich kürzer. Die geringere Fläche dürfte mechanisch aber stärker wiegen als die der Einfluss auf die EMV... =Wer will?= Ich habe noch ein paar Platinchen herumliegen. Wer will kann ein paar (gegen Versandkosten) haben. =Downloads= [[Datei:minipsu.zip]] =Weblinks= * [http://schmidt-walter-schaltnetzteile.de/smps/smps.html Dr. Schmidt-Walter - Dimensionierung von Schaltnetzteilen] * [http://powerelectronics.com/site-files/powerelectronics.com/files/archive/powerelectronics.com/mag/606PET25.pdf D. Schelle und J. Castorenoa - Buck-Converter Design Demystified] [[Kategorie:Elektronik]] [[Kategorie:Stromversorgung]] f0f1fec778ff365b9cfafe567f8c291901c948b3 Datei:Minipsu v1 foto.jpg 6 404 975 2015-04-01T17:40:37Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Hobbyelektronik.org:Datenschutz 4 6 981 12 2015-04-02T12:45:34Z Chris 2 wikitext text/x-wiki =Geltungsbereich= Diese Datenschutzerklärung klärt Nutzer über die Art, den Umfang und Zwecke der Erhebung und Verwendung personenbezogener Daten durch hobbyelektronik.org ([[Hobbyelektronik.org:Impressum|Impressum]] auf. Die rechtlichen Grundlagen des Datenschutzes finden sich im [http://www.gesetze-im-internet.de/bdsg_1990/ Bundesdatenschutzgesetz] (BDSG) und dem [http://www.gesetze-im-internet.de/tmg/index.html Telemediengesetz] (TMG). =Zugriffsdaten/Server-Logfiles= Unser Webspace-Provider erhebt Daten über jeden Zugriff auf das Angebot (so genannte Serverlogfiles). Zu den Zugriffsdaten gehören: * Name der abgerufenen Webseite, Datei, Datum und Uhrzeit des Abrufs, übertragene Datenmenge, Meldung über erfolgreichen Abruf, Browsertyp nebst Version, das Betriebssystem des Nutzers, Referrer URL (die zuvor besuchte Seite), IP-Adresse und der anfragende Provider. * Wir verwenden die Protokolldaten nur für statistische Auswertungen zum Zweck des Betriebs, der Sicherheit und der Optimierung des Angebotes. Wir behalten uns jedoch vor, die Protokolldaten nachträglich zu überprüfen, wenn aufgrund konkreter Anhaltspunkte der berechtigte Verdacht einer rechtswidrigen Nutzung besteht. =Umgang mit personenbezogenen Daten= Personenbezogene Daten sind Informationen, mit deren Hilfe eine Person bestimmbar ist, also Angaben, die zurück zu einer Person verfolgt werden können. Dazu gehören der Name, die Emailadresse oder die Telefonnummer. Aber auch Daten über Vorlieben, Hobbies, Mitgliedschaften oder welche Webseiten von jemandem angesehen wurden zählen zu personenbezogenen Daten. Personenbezogene Daten werden uns nur dann erhoben, genutzt und weiter gegeben, wenn dies gesetzlich erlaubt ist oder die Nutzer in die Datenerhebung einwilligen. =Kontaktaufnahme= Bei der Kontaktaufnahme mit uns (zum Beispiel per Kontaktformular oder E-Mail) werden die Angaben des Nutzers zwecks Bearbeitung der Anfrage sowie für den Fall, dass Anschlussfragen entstehen, gespeichert. =Kommentare und Beiträge= Wenn Nutzer Kommentare im Blog oder sonstige Beiträge hinterlassen, werden ihre IP-Adressen gespeichert. Das erfolgt zu unserer Sicherheit, falls jemand in Kommentaren und Beiträgen widerrechtliche Inhalte schreibt (Beleidigungen, verbotene politische Propaganda, etc.). In diesem Fall können wir selbst für den Kommentar oder Beitrag belangt werden und ist daher an der Identität des Verfassers interessiert. =Einbindung von Diensten und Inhalten Dritter= Es kann vorkommen, dass innerhalb dieses Onlineangebotes Inhalte Dritter, wie zum Beispiel Videos von YouTube, Kartenmaterial von Google-Maps, RSS-Feeds oder Grafiken von anderen Webseiten eingebunden werden. Dies setzt immer voraus, dass die Anbieter dieser Inhalte (nachfolgend bezeichnet als "Dritt-Anbieter") die IP-Adresse der Nutzer wahrnehmen. Ohne die IP-Adresse könnten sie die Inhalte nicht an den Browser des jeweiligen Nutzers ausliefern. Die IP-Adresse ist damit für die Darstellung dieser Inhalte erforderlich. Wir bemühen uns nur solche Inhalte zu verwenden, deren jeweilige Anbieter die IP-Adresse lediglich zur Auslieferung der Inhalte verwenden. Jedoch haben wir keinen Einfluss darauf, falls die Dritt-Anbieter die IP-Adresse z. B. für statistische Zwecke speichern. Soweit dies uns bekannt ist, klären wir die Nutzer darüber auf. =Cookies= Cookies sind kleine Dateien, die es ermöglichen, auf dem Zugriffsgerät der Nutzer (PC, Smartphone o. ä.) spezifische, auf das Gerät bezogene Informationen zu speichern. Sie dienen zum einem der Benutzerfreundlichkeit von Webseiten und damit den Nutzern (z. B. Speicherung von Logindaten). Zum anderen dienen sie, um die statistische Daten der Webseitennutzung zu erfassen und sie zwecks Verbesserung des Angebotes analysieren zu können. Die Nutzer können auf den Einsatz der Cookies Einfluss nehmen. Die meisten Browser verfügen eine Option mit der das Speichern von Cookies eingeschränkt oder komplett verhindert wird. Allerdings wird darauf hingewiesen, dass die Nutzung und insbesondere der Nutzungskomfort ohne Cookies eingeschränkt werden kann. =Widerruf, Änderungen, Berichtigungen und Aktualisierungen= Der Nutzer hat das Recht, auf Antrag unentgeltlich Auskunft zu erhalten über die personenbezogenen Daten, die über ihn gespeichert wurden. Zusätzlich hat der Nutzer das Recht auf Berichtigung unrichtiger Daten, Sperrung und Löschung seiner personenbezogenen Daten, soweit dem keine gesetzliche Aufbewahrungspflicht entgegensteht. bed8c1cbac6a029c268e13daabf83eb44377cb92 982 981 2015-04-02T12:45:50Z Chris 2 wikitext text/x-wiki =Geltungsbereich= Diese Datenschutzerklärung klärt Nutzer über die Art, den Umfang und Zwecke der Erhebung und Verwendung personenbezogener Daten durch hobbyelektronik.org ([[Hobbyelektronik.org:Impressum|Impressum]]= auf. Die rechtlichen Grundlagen des Datenschutzes finden sich im [http://www.gesetze-im-internet.de/bdsg_1990/ Bundesdatenschutzgesetz] (BDSG) und dem [http://www.gesetze-im-internet.de/tmg/index.html Telemediengesetz] (TMG). =Zugriffsdaten/Server-Logfiles= Unser Webspace-Provider erhebt Daten über jeden Zugriff auf das Angebot (so genannte Serverlogfiles). Zu den Zugriffsdaten gehören: * Name der abgerufenen Webseite, Datei, Datum und Uhrzeit des Abrufs, übertragene Datenmenge, Meldung über erfolgreichen Abruf, Browsertyp nebst Version, das Betriebssystem des Nutzers, Referrer URL (die zuvor besuchte Seite), IP-Adresse und der anfragende Provider. * Wir verwenden die Protokolldaten nur für statistische Auswertungen zum Zweck des Betriebs, der Sicherheit und der Optimierung des Angebotes. Wir behalten uns jedoch vor, die Protokolldaten nachträglich zu überprüfen, wenn aufgrund konkreter Anhaltspunkte der berechtigte Verdacht einer rechtswidrigen Nutzung besteht. =Umgang mit personenbezogenen Daten= Personenbezogene Daten sind Informationen, mit deren Hilfe eine Person bestimmbar ist, also Angaben, die zurück zu einer Person verfolgt werden können. Dazu gehören der Name, die Emailadresse oder die Telefonnummer. Aber auch Daten über Vorlieben, Hobbies, Mitgliedschaften oder welche Webseiten von jemandem angesehen wurden zählen zu personenbezogenen Daten. Personenbezogene Daten werden uns nur dann erhoben, genutzt und weiter gegeben, wenn dies gesetzlich erlaubt ist oder die Nutzer in die Datenerhebung einwilligen. =Kontaktaufnahme= Bei der Kontaktaufnahme mit uns (zum Beispiel per Kontaktformular oder E-Mail) werden die Angaben des Nutzers zwecks Bearbeitung der Anfrage sowie für den Fall, dass Anschlussfragen entstehen, gespeichert. =Kommentare und Beiträge= Wenn Nutzer Kommentare im Blog oder sonstige Beiträge hinterlassen, werden ihre IP-Adressen gespeichert. Das erfolgt zu unserer Sicherheit, falls jemand in Kommentaren und Beiträgen widerrechtliche Inhalte schreibt (Beleidigungen, verbotene politische Propaganda, etc.). In diesem Fall können wir selbst für den Kommentar oder Beitrag belangt werden und ist daher an der Identität des Verfassers interessiert. =Einbindung von Diensten und Inhalten Dritter= Es kann vorkommen, dass innerhalb dieses Onlineangebotes Inhalte Dritter, wie zum Beispiel Videos von YouTube, Kartenmaterial von Google-Maps, RSS-Feeds oder Grafiken von anderen Webseiten eingebunden werden. Dies setzt immer voraus, dass die Anbieter dieser Inhalte (nachfolgend bezeichnet als "Dritt-Anbieter") die IP-Adresse der Nutzer wahrnehmen. Ohne die IP-Adresse könnten sie die Inhalte nicht an den Browser des jeweiligen Nutzers ausliefern. Die IP-Adresse ist damit für die Darstellung dieser Inhalte erforderlich. Wir bemühen uns nur solche Inhalte zu verwenden, deren jeweilige Anbieter die IP-Adresse lediglich zur Auslieferung der Inhalte verwenden. Jedoch haben wir keinen Einfluss darauf, falls die Dritt-Anbieter die IP-Adresse z. B. für statistische Zwecke speichern. Soweit dies uns bekannt ist, klären wir die Nutzer darüber auf. =Cookies= Cookies sind kleine Dateien, die es ermöglichen, auf dem Zugriffsgerät der Nutzer (PC, Smartphone o. ä.) spezifische, auf das Gerät bezogene Informationen zu speichern. Sie dienen zum einem der Benutzerfreundlichkeit von Webseiten und damit den Nutzern (z. B. Speicherung von Logindaten). Zum anderen dienen sie, um die statistische Daten der Webseitennutzung zu erfassen und sie zwecks Verbesserung des Angebotes analysieren zu können. Die Nutzer können auf den Einsatz der Cookies Einfluss nehmen. Die meisten Browser verfügen eine Option mit der das Speichern von Cookies eingeschränkt oder komplett verhindert wird. Allerdings wird darauf hingewiesen, dass die Nutzung und insbesondere der Nutzungskomfort ohne Cookies eingeschränkt werden kann. =Widerruf, Änderungen, Berichtigungen und Aktualisierungen= Der Nutzer hat das Recht, auf Antrag unentgeltlich Auskunft zu erhalten über die personenbezogenen Daten, die über ihn gespeichert wurden. Zusätzlich hat der Nutzer das Recht auf Berichtigung unrichtiger Daten, Sperrung und Löschung seiner personenbezogenen Daten, soweit dem keine gesetzliche Aufbewahrungspflicht entgegensteht. 6b3cefd5c191b39bf2a31a9efcbcb70b0c263cf9 983 982 2015-04-02T12:46:36Z Chris 2 wikitext text/x-wiki =Geltungsbereich= Diese Datenschutzerklärung klärt Nutzer über die Art, den Umfang und Zwecke der Erhebung und Verwendung personenbezogener Daten durch hobbyelektronik.org ([[Hobbyelektronik.org:Impressum|Impressum]]) auf. Die rechtlichen Grundlagen des Datenschutzes finden sich im [http://www.gesetze-im-internet.de/bdsg_1990/ Bundesdatenschutzgesetz] (BDSG) und dem [http://www.gesetze-im-internet.de/tmg/index.html Telemediengesetz] (TMG). =Zugriffsdaten/Server-Logfiles= Unser Webspace-Provider erhebt Daten über jeden Zugriff auf das Angebot (so genannte Serverlogfiles). Zu den Zugriffsdaten gehören: * Name der abgerufenen Webseite, Datei, Datum und Uhrzeit des Abrufs, übertragene Datenmenge, Meldung über erfolgreichen Abruf, Browsertyp nebst Version, das Betriebssystem des Nutzers, Referrer URL (die zuvor besuchte Seite), IP-Adresse und der anfragende Provider. * Wir verwenden die Protokolldaten nur für statistische Auswertungen zum Zweck des Betriebs, der Sicherheit und der Optimierung des Angebotes. Wir behalten uns jedoch vor, die Protokolldaten nachträglich zu überprüfen, wenn aufgrund konkreter Anhaltspunkte der berechtigte Verdacht einer rechtswidrigen Nutzung besteht. =Umgang mit personenbezogenen Daten= Personenbezogene Daten sind Informationen, mit deren Hilfe eine Person bestimmbar ist, also Angaben, die zurück zu einer Person verfolgt werden können. Dazu gehören der Name, die Emailadresse oder die Telefonnummer. Aber auch Daten über Vorlieben, Hobbies, Mitgliedschaften oder welche Webseiten von jemandem angesehen wurden zählen zu personenbezogenen Daten. Personenbezogene Daten werden uns nur dann erhoben, genutzt und weiter gegeben, wenn dies gesetzlich erlaubt ist oder die Nutzer in die Datenerhebung einwilligen. =Kontaktaufnahme= Bei der Kontaktaufnahme mit uns (zum Beispiel per Kontaktformular oder E-Mail) werden die Angaben des Nutzers zwecks Bearbeitung der Anfrage sowie für den Fall, dass Anschlussfragen entstehen, gespeichert. =Kommentare und Beiträge= Wenn Nutzer Kommentare im Blog oder sonstige Beiträge hinterlassen, werden ihre IP-Adressen gespeichert. Das erfolgt zu unserer Sicherheit, falls jemand in Kommentaren und Beiträgen widerrechtliche Inhalte schreibt (Beleidigungen, verbotene politische Propaganda, etc.). In diesem Fall können wir selbst für den Kommentar oder Beitrag belangt werden und ist daher an der Identität des Verfassers interessiert. =Einbindung von Diensten und Inhalten Dritter= Es kann vorkommen, dass innerhalb dieses Onlineangebotes Inhalte Dritter, wie zum Beispiel Videos von YouTube, Kartenmaterial von Google-Maps, RSS-Feeds oder Grafiken von anderen Webseiten eingebunden werden. Dies setzt immer voraus, dass die Anbieter dieser Inhalte (nachfolgend bezeichnet als "Dritt-Anbieter") die IP-Adresse der Nutzer wahrnehmen. Ohne die IP-Adresse könnten sie die Inhalte nicht an den Browser des jeweiligen Nutzers ausliefern. Die IP-Adresse ist damit für die Darstellung dieser Inhalte erforderlich. Wir bemühen uns nur solche Inhalte zu verwenden, deren jeweilige Anbieter die IP-Adresse lediglich zur Auslieferung der Inhalte verwenden. Jedoch haben wir keinen Einfluss darauf, falls die Dritt-Anbieter die IP-Adresse z. B. für statistische Zwecke speichern. Soweit dies uns bekannt ist, klären wir die Nutzer darüber auf. =Cookies= Cookies sind kleine Dateien, die es ermöglichen, auf dem Zugriffsgerät der Nutzer (PC, Smartphone o. ä.) spezifische, auf das Gerät bezogene Informationen zu speichern. Sie dienen zum einem der Benutzerfreundlichkeit von Webseiten und damit den Nutzern (z. B. Speicherung von Logindaten). Zum anderen dienen sie, um die statistische Daten der Webseitennutzung zu erfassen und sie zwecks Verbesserung des Angebotes analysieren zu können. Die Nutzer können auf den Einsatz der Cookies Einfluss nehmen. Die meisten Browser verfügen eine Option mit der das Speichern von Cookies eingeschränkt oder komplett verhindert wird. Allerdings wird darauf hingewiesen, dass die Nutzung und insbesondere der Nutzungskomfort ohne Cookies eingeschränkt werden kann. =Widerruf, Änderungen, Berichtigungen und Aktualisierungen= Der Nutzer hat das Recht, auf Antrag unentgeltlich Auskunft zu erhalten über die personenbezogenen Daten, die über ihn gespeichert wurden. Zusätzlich hat der Nutzer das Recht auf Berichtigung unrichtiger Daten, Sperrung und Löschung seiner personenbezogenen Daten, soweit dem keine gesetzliche Aufbewahrungspflicht entgegensteht. b4d82aaaac84e65dd5b9af1cbc116c03b9251673 Datei:Minipsu v2.1 brd.png 6 405 985 2015-04-04T20:45:18Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Mini-Schaltwandler 0 403 986 979 2015-04-04T20:51:55Z Chris 2 Version 2.1 - noch ein Gimmick mehr ;) wikitext text/x-wiki [[Datei:Minipsu v1 foto.jpg|thumb|Mini-Schaltwandler neben einem 7805]] Die meisten elektronischen Schaltungen haben eine geregelte Stromversorgung. Früher hat man dafür oft und gerne ein Bauteil aus der 78xx-Reihe verwendet. Ganz einfach, weil sie günstig sind, zuverlässig arbeiten und wenig Außenbeschaltung benötigen. Der große Nachteil an Linearreglern allgemein ist die in vielen Anwendungsfällen eher dürftige Effizienz und noch vielmehr die notwendige Kühlung, denn: Das Produkt aus Spannungsdifferenz zwischen Ein- und Ausgang und dem Strom, der durch den Regler fließt, ist ziemlich genau die Leistung, die man wegkühlen muss. Beispiel: ein 7805-Regler wird mit 12 V versorgt und soll eine Schaltung versorgen, die 200 mA benötigt: :<math>P = \left(U_{\textrm{in}}-U_{\textrm{out}}\right) \cdot I = \left(12\textrm{ V}-5\textrm{ V}\right) \cdot 0.2 \textrm{ A} = 1.4\textrm{ W}</math> Nicht weltbeltbewegend, aber immerhin. Die Effizienz von diesem Regler liegt bei :<math>\eta = \frac{P_\textrm{out}}{P_\textrm{in}}= \frac{U_\textrm{out} \cdot I_\textrm{out}}{U_\textrm{in} \cdot I_\textrm{in}}</math> wobei der Eigenbedarf der meisten Linearregler vernachlässigbar gering ist (also der Unterschied zwischen I_out und I_in), somit lassen sich die Ströme einfach kürzen und die Effizienz ist rein von den Spannungen abhängig. Im Beispiel oben ergibt sich ein Wirkungsgrad von etwa 42 %. Ziemlich mies. Mit einem Abwärtswandler (auch step-down- oder buck-converter) kann man mit - im Vergleich zu Linearreglern - etwas größerem Schaltungsaufwand deutlich bessere Ergebnisse erzielen. Dabei wird der Strom "zerhackt" und über ein Speicherelement (in aller Regel eine Induktivität) geglättet. Die Ausgangsspannung hängt dabei vom Tastverhältnis des Schalters ab. Vereinfacht gesagt: je länger dieser geschlossen ist, desto mehr Energie wird vom Eingang zum Ausgang transportiert. Der Wirkungsgrad hängt bei hierbei von mehreren Faktoren ab: * Schalttransistor * Freilaufdiode * Induktivität So toll das Prinzip ist, es hat nicht nur Vorteile. Beispielsweise hat man höhere Anforderungen an das Layout und Risiken, wenn es um das Bestehen von EMV-Zulassungen geht. Schließlich leben diese Schaltungen von steilen Flanken und mitunter kurzzeitig hohen Strömen. Außerdem sieht man am Ausgang oft deutlich größere Störungen als bei Linearreglern. Hinzu kommt noch, dass Schaltwandler aufgrund ihres Aufbaus deutlich Lastspezifischer sind. Sie sind als nicht DIE Lösung für eine Stromversorgung, sondern eine mögliche Art dafür. =Der Mini-Schaltwandler (Version 1)= Ich wollte einen kleinen und halbwegs flexibel einsetzbaren Schaltwandler haben, den man statt einem 78xx verwenden kann, natürlich nicht zu teuer. In Sachen Leistung ruhig mit Abstrichen - die meisten Anwendungen benötigen selten über 0,5 A. Eingangsspannung bis 20 V sollte ok sein, gerne aber auch etwas mehr. ==Bauteilauswahl== Bei der Suche bei Farnell bin ich schnell fündig geworden: Der [http://www.microchip.com/wwwproducts/devices.aspx?dDocName=en554058 MCP16301] von Microchip. Im SOT-23-6-Gehäuse ist er zwar klein, aber noch gut per Hand lötbar, der Eingangsspannungsbereich ist angenehm groß. Der Ausgangsstrom ist mit 0,6 A mehr als hinreichend und die 500 kHz Schaltfrequenz erfordern eine relativ kleine Induktivität. Der Preis ist mit etwas um einen Euro fair. Und zu guter Letzt ist er mittlerweile auch bei Reichelt verfügbar. Nach dem IC kommt die Induktivität. Abschnitt 5.6 gibt einige Hinweise zur Auswahl samt Beispiele. Für den interessanten Bereich zwischen 2,0 bis 5 V Ausgangsspannung sollen es also 10 bis 22 µH sein und ein Sättigungsstrom von mindestens 760 mA wird empfohlen. Kurz durch den Reichelt-Katalog geblättert finden sich die Fastron 1616 FPS. Da mein Ziel erst einmal 3,3 V sind, soll es die 15 µH-Variante werden, wobei es auch passende mit 22 und 33 µH gibt. Leider wird der kleine Footprint von 4,2 x 4,2 mm² durch einen etwas schlechteren ESR erkauft. Wer Platz hat, greift lieber zur 242408 oder 242418 - diese versprechen eine etwas höhere Effizienz! Fehlt noch die Schaltdiode als Kernkomponente. Diese sollte klein und schnell sein und etwa 1 A können. Bei der Spannungsfestigkeit sollten 30 V reichen - mehr kann der MCP eh nicht. Die [http://www.reichelt.de/index.html?ACTION=3&GROUPID=2991&ARTICLE=146621 SS 13L] von Taiwan Semiconductor passt. Zur Glättung empfiehlt das Datenblatt 1 µF bis 10 µF am Eingang und 10 µF bis 22 µF am Ausgang (wobei es zwischen den Application Examples und der Empfehlung in Tabelle 5-2 etwas widersprüchlich ist). Um es generisch zu halten: 10 µF am Eingang, 22 µF am Ausgang. Hat Reichelt jeweils im 1206-Package, ist aber leider nicht so ganz billig. Wer Zugriff auf Farnell hat, bekommt mehr und vermutlich auch eine günstigere Auswahl. Der Schaltwandler-IC verwendet einen n-Kanal-FET als Schalter. Da sich dieser - wie von der Topologie gefordert - auf der High-Side befinden und U<sub>GS</sub> > U<sub>th</sub> sein muss, wird eine Hilfsspannung größer als U<sub>in</sub> benötigt. Eine Schaltung mit p-Kanal-FET wäre zwar sicher einfacher, würde aber leichte Abstriche im Wirkungsgrad bedeuten (idR. höherer R<sub>ds,on</sub>). Wie dem auch sei, die Hilfsspannung bekommt man fast geschenkt, indem man den Schalttransistor und die Induktivität als Ladungspumpe verwendet. Dazu benötigt man zusätzlich lediglich eine Diode und einen Kondensator. Damit das auch funktioniert, darf der FET nie durchgängig eingeschaltet sein - sonst wird nichts mehr gepumpt und er kann nicht mehr geschaltet werden. Da die benötigte Leistung durchweg niedrig ist, reichen Wald- und Wiesenkomponenten. Wie im Datenblatt vorgeschlagen eine 1N4148 und ein 100 nF-Kerko. Fehlen noch die Feedback-Widerstände. Um das verwenden zu können, was vielleicht sogar in der Grabbelkiste liegt, empfehle ich das Tool [http://www.muellerzumhagen.de/index.php/sascha/tools/widerstand-ist-zwecklos Widerstand ist Zwecklos], das direkt ein Werkzeug zum Ermitteln von Widerständen für Spannungsregler bietet. Vref ist mit 0,8 V zu wählen. Für 3,3 V gibt es aus der E6-Reihe ein sehr gut passendes Pärchen, für 5 V muss man entweder auf die E24-Reihe ausweichen, oder 3 Widerstände verwenden: {| class="wikitable" |- ! U<sub>out,target</sub> [V] !! Reihe !! R<sub>upper</sub> [Ohm] !! R<sub>lower</sub> [Ohm] !! U<sub>out</sub> (worst case) [V] |- | 3,3 || E6 || 47 k || 15 k || 3,307 (3,249 ... 3,349) |- | 5 || E24 || 27 k || 5,1 k || 5,035 (4,942 ... 5,111) |- | 5 || E24 || 36 k || 6,8 k || 5,035 (4,939 ... 5,108) |- | 5 || E6 || 33 k p 100 k || 4,7 k || 5,0233 (4,942 ... 5,111) |- | 5 || E6 || 47 k p 150 k || 6,8 k || 5,0102 (4,930 ... 5,098) |- |} Es ergibt sich folgende BOM: {| class="wikitable" |- ! Komponente !! Menge !! Reichelt Bestellname !! Preis [€] !! Farnell Bestellnummer !! Preis [€] |- | Microchip MCP16301 || 1 || MCP 16301T-I/CHY || 1,15 || 2009288 || 1,21 |- | Fastron 1616FPS 15µH || 1 || L-1616FPS 15µ || 0,22 || 2345178* || 1,15 |- | TSC SS13L || 1 || SS 13L || 0,11 || 1559158 || 0,1 |- | 1N4148 || 1 || 1N 4148 SMD || 0,02 || 1612361 || 0,04 |- | 100nF-Kerko || 1 || X7R-G0603 100N || 0,15 || * || 0,01 |- | 10µF/25V || 1 || X7R-G1206 10/25 || 0,24 || * || 0,25 |- | 22µF/6V || 1 || X5R-G0805 22/6 || 0,07 || * || 0,15 |- | 47kOhm 0603 || 1 || SMD-0603 47K || 0,1 || * || 0,01 |- | 15kOhm 0603 || 1 || SMD-0603 15K || 0,1 || * || 0,01 |- |} Für die Induktivität habe ich bei Farnell eine halbwegs gleichwertige ausgewählt, bei den Nicht-Kernkomponenten habe stehen die jeweils annehmbaren Preise ohne auf ein spezielles Produkt zu verweisen. Bei Reichelt kosten die Bauteile für einen Schaltregler 2,16 Euro, bei Farnell (inkl. MwSt.) 2,93 Euro. Trotzdem kann sich (bis auf die Spule) der Kauf bei Farnell - sofern man dort bestellen kann - durch die Preisstaffeln lohnen. ==Stromlaufplan== Der Stromlaufplan ist reichlich unspektakulär, er ist nicht viel mehr als eine der Application Notes im Datenblatt. <gallery> Datei:minipsu_v1_sch.png|Stromlaufplan des Schaltreglers </gallery> ==Layout== Das Layout ist da ein bisschen aufwändiger. Wie in der Einleitung angedeutet, soll es ein Ersatz für die 78xx werden. Das heißt: gleicher Formfaktor. Laut einem zufällig herausgezogenen [http://www.ti.com/lit/ds/symlink/lm340-n.pdf Datenblatt] ist das Package in im Mittel 10,16 x 14,99 mm² groß und 4,58 mm dick. Das gilt es anzustreben. Der Anschluss erfolgt, wie schon im Stromlaufplan zu sehen ist, über eine zweireihige Stiftleiste, die der Pinbelegung der gängigen Regler folgt. Der Konnektor ist allerdings nicht stehend, sondern liegend am Rand der Leiterkarte vorgesehen (demnächst in der [[EAGLE-Bibliotheken|EAGLE-Bibliothek]] verfügbar). Selbstverständlich muss man keine 6-polige Stiftleiste anlöten, es reicht eine dreipolige. Wenn überhaupt. Mit entsprechenden Pads auf der Hauptplatine kann man den Regler entweder stehend auflöten oder über eine Stiftleiste durch die Durchkontaktierungen auch liegend montieren. Möchte man sich die Stiftleiste sparen, kann man das Modul auch auf Höhe der Durchkontaktierungen absägen und an diesen liegend über die nun offengelegten Pads am Leiterkartenrand befestigen. Die Anschlussbelegung hat schon eine nicht zu unterschätzende Auswirkung auf die Platzierung der restlichen Bauteile. Gleichzeitig muss man auf allgemeine Designregeln für Schaltwandler achten - [http://www.lothar-miller.de/s9y/categories/40-Layout-Schaltregler Lothar Miller] hat hierfür einen sehr guten Artikel geschrieben. Um diesen Regeln gerecht zu werden hilf nur: Platzieren, überprüfen, neu platzieren, nochmal überprüfen und das behalten, mit dem man am wenigsten unglücklich ist. Das perfekte Design schafft man wohl nur extrem selten. Denn: wenn es in Bezug auf Strompfade gut ist, kann einem die Thermik oder die Platzierung von anderen Modulen (ok, hier nicht) in die Suppe spucken. Ich bin bei folgendem Layout angekommen: <gallery> Datei:minipsu_v1_brd.png|Layout des Schaltreglers </gallery> Außenmaße: 10,41 x 15,08 mm². Nur ein kleines bisschen oberhalb des gesteckten Ziels aber noch innerhalb der mechanischen Specs von TI ;-) Manche werden sich vielleicht fragen, warum die Ausgangsspannung über die untere Lage zum Spannungsteiler für das Feedback führt - das könnte man doch direkt an der Diode rechts oben abgreifen.... Ja, könnte man machen, aber dann wär's halt kacke. Abgesehen von dem blöden Spruch gibt es natürlich auch einen sinnvollen Grund dafür: Wo Strom fließt, fällt Spannung ab. An der Diode oben bzw. nahe an der Induktivität fließen mitunter etwas größere Ströme - wodurch sich die Messung verfälschen könnte. In der Praxis könnte man zwar probieren, ob es auch so geht, aber es gibt 1. keine Notwendigkeit dafür und 2. hat man bei anderen Designs weniger Probleme, wenn man sich gleich an vernünftiges Sensing gewöhnt. ==Betrachtung der Strompfade== Anhand der Millerschen Strompfadbilder lässt sich relativ leicht ermitteln, ob man einen groben Schnitzer im Design hat. Interessant sind die Strompfade in den drei verschiedenen Phasen des Schaltwandlers, die ich wie folgt sowohl im Stromlaufplan als auch im Layout hervorgehoben habe: * Laden: gelb * Freilauf/Leerlauf: orange * Recovery: blau <gallery> Datei:minipsu_v1_strompfad_sch.png|Strompfad im Stromlaufplan Datei:minipsu_v1_strompfad_brd.png|Strompfad im Layout </gallery> Das sieht schon ganz ok aus, wenn auch noch nicht optimal. Die Strecke links von C1 zu IC1 ist verhältnismäßig lang. Das gibt unnötige Induktivität, Widerstand und Abstrahlfläche. Dafür ist alles wichtige des Schaltwandlers auf einer Lage, was ebenfalls die Fläche klein hält. Unter der Induktivität befindet sich auf gleicher Lage Freischnitt des Kupfers. Leiterbahnen sollte man selbstverständlich soweit wie es geht fern halten. Bezüglich Aussparungen des Kupfers auf der/den anderen Lage(n) kann man streiten. Hier steht Einkopplung von Störströmen auf andere Signale oder die Massefläche und das Abblocken des Feldes (EMV) nach außen auf im Gegensatz... Hier ist noch anzumerken, dass das Layout der Leiterkarten leicht unterschiedlich zu den hier gezeigten Fotos ist. ==Aufbau== Ein paar Wochen später sind die gefertigten Leiterkarten auch [http://hobbyelektronik.org/b/2014/10/sie-sind-da/ angekommen] - ein paar Monate später wurden dann auch die Bauteile bestellt. Für die Bestückung sind etwas Feingefühl und eine dünne Lötspitze gefragt. ==Messungen== Keine Behauptungen ohne Beweise, in diesem Fall Messungen. Mit dem Labornetzteil und meinem einfachen DMM ließ sich grundlegend bestätigen: Ja, es funktioniert! Bei den festgelegten 3,3 V Ausgangsspannung fing der Regler bei etwa 3,7 V an, vernünftig zu arbeiten. Das hat zwei Gründe: Wie oben beschrieben, muss der Duty Cycle < 100 % sein, damit die Ladungspumpe zur Erzeugung der Hilfsspannung funktioniert. Nachdem der Maximum Duty Cycle bei typ. 95 % liegt, kann man ganz plump 3,7 V * 0,95 rechnen und landet bei 3,5 Volt. Dann kommt natürlich noch der R<sub>ds,on</sub> des FET und der Innenwiderstand der Induktivität sowie Schaltverluste dazu. Alles in allem: plausibel. Ein wichtiges Merkmal für den Betrieb ist natürlich der Wirkungsgrad. Dazu ermittelt man sowohl auf Ein- als auch Ausgangsseite die Leistung (indem man Strom und Spannung misst) bei bekannter Last und wendet die in der Einleitung gezeigte Formel an. Dies führt man mit verschiedenen Lasten und Eingangsspannungen durch, schmeißt die Daten in die Tabellenkalkulation und lässt es sich plotten: <gallery> Datei:minipsu_v1_wirkungsgrad_1.png|Wirkungsgrad über Last und Eingangsspannung Muster 1 Datei:minipsu_v1_wirkungsgrad_2.png|Wirkungsgrad über Last und Eingangsspannung Muster 2 </gallery> In dem Aufbau habe ich leicht abweichende Widerstandspaarungen als in der oben gezeigten Tabelle verwendet, was allerdings weitestgehend unmaßgeblich ist. Im Diagramm sieht man recht gut, dass mit 92 % der höchste Wirkungsgrad bei 5 V Eingangsspannung und einer Last von 100 mA erreicht wird. Bei den anderen Eingangsspannungen sieht es leider nicht ganz so gut aus. Zudem gibt es bei ca. 0,3 A einen leichten systematischen Einbruch (den ich auch mit einer zweiten Leiterkarte bestätigen konnte). Momentan kann ich allerdings nur mutmaßen, woher das kommt. Aus den Aufzeichnungen lässt sich auch das Verhalten die Ausgangsspannung unter Last darstellen: [[Datei:minipsu_v1_spannung_last_1.png]] Leider war die Auflösung (10 mV) relativ gering, dadurch der Treppeneffekt. Wie man sieht, ist das Verhalten durchaus hinnehmbar. ==Optimierung== Es ist noch nicht Ende Fahnenstange - aus dem Design kann man sicher mehr herauskitzeln. Die größten Kandidaten sind sicherlich die Induktivität und die Freilaufdiode, dann kommen irgendwann die Kondensatoren. Man könnte natürlich auch den IC austauschen, aber dann hat man zwangsläufig ein anderes Design. Ein weiterer Punkt wäre die Diode in der Boost-Schaltung - leckt diese zu stark, kann der FET evtl. nicht vollständig durchschalten. Da gerade keine passenden Alternativen für Induktivität und Kondensatoren herumliegen, bleiben nur noch die Dioden. Als Schaltdiode liegt noch eine [https://www.toshiba.com/taec/components2/Datasheet_Sync/200612/DST_CRS08-TDE_EN_1640.pdf CRS08 von Toshiba], für die Boost-Diode eine [http://www.vishay.com/docs/85508/bat54v.pdf BAT54] (Schottky) herum. <gallery> Datei:minipsu_v1_wirkungsgrad_CRS08.png|CRS08 als Schaltdiode Datei:minipsu_v1_wirkungsgrad_BAT54C.png|BAT54 als Boost-Diode </gallery> Die CRS08 reißt im Mittel einen 0,6 % höheren Wirkungsgrad heraus, die BAT54 0,4 %. Mal ganz abgesehen von Messungenauigkeiten oder Wiederholbarkeit... Für die eine andere Spule muss ich auf den nächsten Karton aus Sande warten, verspreche mir aber noch eine leichte Verbesserung. =Version 2= Es geht kleiner und ein bisschen besser. ==Layout== Die BAT43WS kostet unwesentlich mehr und dürfte die Performance ein kleines Stück verbessern - gleichzeitig ist sie ein gutes Stück kleiner als die die Diode in Minimelf-Gehäuse. Der Eingangs-Kondensator ist nach ist gedreht und etwas nach oben gewandert. Das erfordert zwar, dass die Versorgung über Durchkontaktierungen geführt wird, was an dieser Stelle relativ unproblematisch sein sollte. Durch das Verschieben kann sowohl die Schaltdiode als auch der IC nach unten verschoben werden. <gallery> Datei:minipsu_v2_sch.png|Stromlaufplan von Version 2 Datei:minipsu_v2_brd.png|Layout von Version 2 </gallery> Größe: 9,6 x 13,7 mm² Auf der Unterseite befindet sich nun im Silkscreen eine Tabelle für die gesetzte Spannung: 3,3 V, 5 V und ein freies Feld. Ferner gibt es für die liegende Montage auf der gegenüberliegenden Seite der Anschlüsse noch ein mit der Masse verbundenes Lötpad. ==Betrachtung der Strompfade== Neuer Anlauf: <gallery> Datei:minipsu_v2_strompfad_brd.png|Strompfad im Layout </gallery> Die Pfade sind jetzt deutlich kürzer. Die geringere Fläche dürfte mechanisch aber stärker wiegen als die der Einfluss auf die EMV... =Version 2.1= Ein kleiner Kniff ist mir noch eingefallen: Durch leichtes verschieben des "rechten" Widerstands und vergrößern dessen Pads (in dem Fall habe ich lediglich ein Polygon im Kupfer und im Lötstopp hinzugefügt) kann man ein Lötflächen im 2,54 mm-Raster erzeugen. Statt den Widerständen kann so auch ein Potenziometer (z. B. das [http://www.reichelt.de/?ACTION=3&ARTICLE=2710 64W-50K] von Reichelt) liegend anlöten: <gallery> Datei:Minipsu_v2.1_brd.png|Bestückungsmöglichkeit für ein Potenziometer (gelb) </gallery> =Wer will?= Ich habe noch ein paar Platinchen herumliegen. Wer will kann ein paar (gegen Versandkosten) haben. =Downloads= [[Datei:minipsu.zip]] =Weblinks= * [http://schmidt-walter-schaltnetzteile.de/smps/smps.html Dr. Schmidt-Walter - Dimensionierung von Schaltnetzteilen] * [http://powerelectronics.com/site-files/powerelectronics.com/files/archive/powerelectronics.com/mag/606PET25.pdf D. Schelle und J. Castorenoa - Buck-Converter Design Demystified] [[Kategorie:Elektronik]] [[Kategorie:Stromversorgung]] 8cbb4dc9b5661cb70b994e1b71e4cb9e89aed546 Datei:Minipsu.zip 6 390 987 984 2015-04-04T21:03:19Z Chris 2 lud eine neue Version von „[[Datei:Minipsu.zip]]“ hoch: Flüchtigkeitsfehler korrigiert. wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ASCII-Tabelle A3 1.pdf 6 406 988 2015-04-10T19:45:00Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ASCII-Tabelle A4 1.pdf 6 407 989 2015-04-10T19:45:01Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ASCII-Tabelle A4 2.pdf 6 408 990 2015-04-10T19:45:02Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e ASCII-Tabelle 0 214 991 843 2015-04-10T19:47:42Z Chris 2 Verschiedene Versionen, auf Druckformate angepasst wikitext text/x-wiki [[Bild:Ascii-Tabelle Ausschnitt.png|thumb|Ausschnitt aus der ASCII-Tabelle]] Beim Programmieren ist der Besitz einer [[wpde:ASCII-Tabelle|ASCII-Tabelle]] oft sehr praktisch. Nur leider habe ich bis noch keine gefunden, die das bietet, was ich will. Deshalb habe ich die Textverarbeitung aktiviert und mich daran gemacht, eine eigene ASCII-Tabelle zu entwerfen. Die Tabelle umfasst zwei Seiten. Wer nur den "normalen" Zeichensatz benötigt, druckt die erste Seite, wer den erweiterten Satz möchte, druckt sich entsprechend beide. Rund um die Tabelle sind die Binäranteile jeder Teile und Spalte abgedruckt, sodass man vom Binärcode relativ schnell zum Zeichen finden kann. In den Kästchen selbst findet sich zum einen das Zeichen selbst, die binäre und darunter die dezimale (links) und hexadezimale (rechts) Entsprechung. Zusätzlich sind diese durch den Suffix d und h markiert. Da man die Steuerzeichen auf Papier direkt nicht richtig abbilden kann, sind die Entsprechungen in Kurzform abgedruckt. Zusätzlich befindet sich darunter (sofern vorhanden) die aus Kommandozeilen bekannte Caret-Notation sowie die Escape-Codes aus C-oiden Sprachen. =Download= [[Datei:ASCII-Tabelle A3_1.pdf|DIN A3 auf einer Seite (Hochformat)]] [[Datei:ASCII-Tabelle A4_1.pdf|DIN A4 auf einer Seite (Hochformat)]] [[Datei:ASCII-Tabelle A4_2.pdf|DIN A4 auf zwei Seiten (Querformat)]] [[Category:Sonstiges]] [[Kategorie:Kleine Helferlein]] 465ab6413a03e2650eb13c7f4501ea2cfaf4b158 992 991 2015-04-10T19:48:00Z Chris 2 ...als Aufzählung wikitext text/x-wiki [[Bild:Ascii-Tabelle Ausschnitt.png|thumb|Ausschnitt aus der ASCII-Tabelle]] Beim Programmieren ist der Besitz einer [[wpde:ASCII-Tabelle|ASCII-Tabelle]] oft sehr praktisch. Nur leider habe ich bis noch keine gefunden, die das bietet, was ich will. Deshalb habe ich die Textverarbeitung aktiviert und mich daran gemacht, eine eigene ASCII-Tabelle zu entwerfen. Die Tabelle umfasst zwei Seiten. Wer nur den "normalen" Zeichensatz benötigt, druckt die erste Seite, wer den erweiterten Satz möchte, druckt sich entsprechend beide. Rund um die Tabelle sind die Binäranteile jeder Teile und Spalte abgedruckt, sodass man vom Binärcode relativ schnell zum Zeichen finden kann. In den Kästchen selbst findet sich zum einen das Zeichen selbst, die binäre und darunter die dezimale (links) und hexadezimale (rechts) Entsprechung. Zusätzlich sind diese durch den Suffix d und h markiert. Da man die Steuerzeichen auf Papier direkt nicht richtig abbilden kann, sind die Entsprechungen in Kurzform abgedruckt. Zusätzlich befindet sich darunter (sofern vorhanden) die aus Kommandozeilen bekannte Caret-Notation sowie die Escape-Codes aus C-oiden Sprachen. =Download= * [[Datei:ASCII-Tabelle A3_1.pdf|DIN A3 auf einer Seite (Hochformat)]] * [[Datei:ASCII-Tabelle A4_1.pdf|DIN A4 auf einer Seite (Hochformat)]] * [[Datei:ASCII-Tabelle A4_2.pdf|DIN A4 auf zwei Seiten (Querformat)]] [[Category:Sonstiges]] [[Kategorie:Kleine Helferlein]] 99cfd6092f6fa760a6c3e07599f0a9e7326f87a1 993 992 2015-04-10T19:50:09Z Chris 2 meh. wikitext text/x-wiki [[Bild:Ascii-Tabelle Ausschnitt.png|thumb|Ausschnitt aus der ASCII-Tabelle]] Beim Programmieren ist der Besitz einer [[wpde:ASCII-Tabelle|ASCII-Tabelle]] oft sehr praktisch. Nur leider habe ich bis noch keine gefunden, die das bietet, was ich will. Deshalb habe ich die Textverarbeitung aktiviert und mich daran gemacht, eine eigene ASCII-Tabelle zu entwerfen. Die Tabelle umfasst zwei Seiten. Wer nur den "normalen" Zeichensatz benötigt, druckt die erste Seite, wer den erweiterten Satz möchte, druckt sich entsprechend beide. Rund um die Tabelle sind die Binäranteile jeder Teile und Spalte abgedruckt, sodass man vom Binärcode relativ schnell zum Zeichen finden kann. In den Kästchen selbst findet sich zum einen das Zeichen selbst, die binäre und darunter die dezimale (links) und hexadezimale (rechts) Entsprechung. Zusätzlich sind diese durch den Suffix d und h markiert. Da man die Steuerzeichen auf Papier direkt nicht richtig abbilden kann, sind die Entsprechungen in Kurzform abgedruckt. Zusätzlich befindet sich darunter (sofern vorhanden) die aus Kommandozeilen bekannte Caret-Notation sowie die Escape-Codes aus C-oiden Sprachen. =Download= * [[Datei:ASCII-Tabelle A3 1.pdf]] DIN A3 auf einer Seite (Hochformat) * [[Datei:ASCII-Tabelle A4 1.pdf]] DIN A4 auf einer Seite (Hochformat) * [[Datei:ASCII-Tabelle A4 2.pdf]] DIN A4 auf zwei Seiten (Querformat) [[Category:Sonstiges]] [[Kategorie:Kleine Helferlein]] 0f09860eacdae6a2023aa076bde4de3b349a4051 Datei:Ascii-Tabelle Ausschnitt.png 6 212 994 586 2015-04-10T19:53:40Z Chris 2 lud eine neue Version von „[[Datei:Ascii-Tabelle Ausschnitt.png]]“ hoch wikitext text/x-wiki Ausschnitt aus der ASCII-Tabelle 4063910f2d5163a0c9f233b2381471714e68fcbd Hauptseite 0 1 995 980 2015-04-10T19:55:29Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *01.04.2015 [[Mini-Schaltwandler]] *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] *02.02.2014 [[EAGLE-Bibliotheken]] *10.11.2013 [[Zeitraffer mit Linux]] ==Änderungen== *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight 62bbc537971fdb1b4667524de721de66ab467e25 1000 995 2015-04-19T19:38:21Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *01.04.2015 [[Mini-Schaltwandler]] *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] *02.02.2014 [[EAGLE-Bibliotheken]] *10.11.2013 [[Zeitraffer mit Linux]] ==Änderungen== *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight 49c026278f4b8e9f855ee1de15eb79a684c27c11 1010 1000 2015-06-14T23:26:57Z Robert 3 /* Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *01.04.2015 [[Mini-Schaltwandler]] *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] *02.02.2014 [[EAGLE-Bibliotheken]] *10.11.2013 [[Zeitraffer mit Linux]] ==Änderungen== *15.06.2015 Ein durchgebranntes [[Netzfilter]] und seine Reparatur *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight 928653e93d8c93a1739c26343f5abe88fdb0dd31 1028 1010 2016-01-02T14:38:09Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *02.01.2016 [[Lichtsensor Avago APDS-9300]] *01.04.2015 [[Mini-Schaltwandler]] *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] *02.02.2014 [[EAGLE-Bibliotheken]] ==Änderungen== *15.06.2015 Ein durchgebranntes [[Netzfilter]] und seine Reparatur *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *19.03.2011 [[What's next?]]: Zimmerbus *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight 6abc8240db9529d1918854cf0b880a119871f1be 1033 1028 2016-03-11T22:22:43Z Chris 2 /* Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *02.01.2016 [[Lichtsensor Avago APDS-9300]] *01.04.2015 [[Mini-Schaltwandler]] *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] *02.02.2014 [[EAGLE-Bibliotheken]] ==Änderungen== *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *15.06.2015 Ein durchgebranntes [[Netzfilter]] und seine Reparatur *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. 42e60a9662fb4935e20a9512dc22c5f277719244 1043 1033 2016-06-23T20:41:15Z Chris 2 Neues wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[http://hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[http://hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *23.06.2016 [[Minichirp]] *02.01.2016 [[Lichtsensor Avago APDS-9300]] *01.04.2015 [[Mini-Schaltwandler]] *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] ==Änderungen== *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *15.06.2015 Ein durchgebranntes [[Netzfilter]] und seine Reparatur *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. 8b475132ccf9046ea52000ec54211e7a3cf1b8de Datei:ZD-939L M Stromlauf grau 1200.png 6 409 996 2015-04-19T19:15:57Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ZD-939L M Detail Schalter 1600 60.jpg 6 410 997 2015-04-19T19:15:58Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Datei:ZD-939L M Schalterfeld 1200 60.jpg 6 411 998 2015-04-19T19:15:58Z Chris 2 MsUpload wikitext text/x-wiki MsUpload 519c08da88276b2f47bc6fb30637d415fd0d804e Kühlung für Zhongdi ZD-939L 0 367 999 910 2015-04-19T19:36:05Z Chris 2 Nachtrag von Manfred - vielen Dank! wikitext text/x-wiki Vor geraumer Zeit hab ich mir eine Zhondi ZD-939L auf den Basteltisch gestellt. Diese Heißluftlötstation ist gerade beim Entlöten von SMD-Bauteilen ein sehr nützlicher Helfer. [[Datei:ZD-939L Hinweis.JPG|thumb|Aufkleber als Workaround]] Eines hat mich allerdings vom ersten Tag weg gestört: sie hat keinen Nachlauf zum Kühlen des Heizelements. Als "Workaround" hat der Importeur lediglich einen Hinweis angebracht, dass man vor dem Abschalten auf die Mindesttemperatur herunterdrehen und eine Minute warten solle. Mit dem Warten kann ich leben, allerdings ist das Einstellen der Temperatur etwas nervig: Minus-Taster drücken und halten und sich für jedes Grad einen Pieps anhören. Nur um beim Nächsten Einschalten genau das Gegenteil zu machen. selbstverständlich ebenfalls mit akustischer Untermalung. Dabei gibt es die Heißluft-Station (neben der Version mit Nachlauf) auch mit dienen Schalter fürs Heizelement. Warum hat das meine nicht? Es wird höchste Zeit, dass sich das ändert. =Analyse= [[Datei:ZD-939L_Innenleben.jpg|thumb|Blick auf die hintere Leiterkarte]] Auf das Ding und reingeschaut. Die Elektronik ist auf 3 Leiterkarten verteilt - hinten befindet sich ein teilbestücktes Board auf das die Netzleitung führt. Nachdem sich nichts darauf befindet, das auf Regelung hindeutet, dürfte es der Leistungsteil sein. Vorne im Gehäuse findet sich neben der Leiterkarte mit den Tastern vom Frontpanel auch die Platine mit dem Display. Die 3 schwarzen Vielbeiner darauf lassen erahnen: hier wird höchstwahrscheinlich geregelt. Heizung abdrehen könnte man nun sowohl auf der Leistungs- als auch der mutmaßlichen Reglerplatine. Man könnte natürlich auch direkt in die Leitung zum Heizelement eingreifen - aber warum sich die Finger an 230 V verbrennen, wenn man es auch einfacher und sicher haben kann? Ein genauerer Blick auf die Display-Platine kann also nicht schaden: <gallery> Datei:ZD-939L Regler.JPG|Die Reglerplatine </gallery> Der 8-beinige Chip links ist ein LM358, also ein Operationsverstärker. Beim mittleren Chip im TQFP-Gehäuse handelt es sich um einen Silabs C8051F310 - einem Mikrocontroller. Rechts im Bild befindet sich ein Holtek HT1621B. Holtek kennt man auch als Mikrocontroller-Hersteller - aber zwei Mikrocontroller für einen einfachen Regler? Nicht ganz. Der Holtek ist lediglich ein LCD-Controller, was auch die Leiterbahnen zu ihm erklärt. Die Regelung übernimmt alleinig der Silabs-Chip. Interessanter als die Regelung und das Display ist für den Umbau, über welche Anschlüsse die Heizung angesteuert wird. Drei der vier Stiftleisten sind mit der Platine hinten verbunden. Die 4-polige Stiftleiste links im Bild führt zur Taster-Platine und fällt damit schon mal weg. Die untere zweipolige Stifleiste ist ein Kandidat - nachdem sie aber verdächtig nahe am LM358, ein paar diskreten Bauteilen und einem Poti liegt, dürfte es sich um den Anschluss für den Temperaturfühler sein. Alle Leitungen außer dieser verbunden bestätigt den Verdacht: Keine Temperaturanzeige. Bleiben nur noch zwei. Die links obere sieht verdächtig nach Stromversorgung aus: etwas dickere Leiterbahnen, Dioden und Kondensatoren. Nicht zuletzt ein 78L05. Warum aber 3 Pins? Eingangsspannung, Masse und Ausgangsspannung? Nein, vermutlich handelt es sich um eine symmetrische Versorgung - entweder fürs Display oder den Operationsverstärker. Ein Blick in den hinteren Teil der Lötstation bestätigt es: Ein Trafo mit Mittelabzapfung. Die Heizung muss also von der Stiftleiste rechts oben angesteuert werden. Am Stecker hängen zwei Drähte, was die Sache leichter macht. Masse lässt sich durchpiepsen und damit ist auch der Ausgang gefunden. Muss nur noch geklärt werden, wann welche Spannung anliegt und ob man einfach so einen Schalter einbringen kann. Multimeter angehängt und den Aparillo losbrummen lassen: 5V, wenn die Heizung an ist. Um sicherzustellen, dass die 5V berührungssicher sind, schnell gegen das Gehäuse, das mit PE verbunden ist: 0V, also galvanisch getrennt. Ausgezeichnet! =Umbau= Ein Ort für den zusätzlichen Schalter ist schnell gefunden: Neben dem Hauptschalter ist noch Platz. Der Akkuschrauber leiert ein Loch in die Platte und der Schalter ist drin. Für die elektrische Verbindung habe ich die Leitung zum "Backpanel" aufgetrennt und den Schalter einfach eingefügt. Da ich die Schaltung dahinter nicht genauer ansehen wollte, habe ich mich für die sicherere Ansteuerung entschlossen - theoretisch könnte man einfach eine der Leitungen auftrennen und den Schalter einfügen. Allerdings bekommt dann die Schaltung "hinten" entweder das Signal vom Mikrocontroller oder floatet durch die Gegend. Da das nicht besonders toll ist, wechselt der Schalter zwischen dem ursprünglichen Pfad und Masse. So gibt es immer einen definierten Pegel und Probleme werden bestmöglich ausgeschlossen. <gallery> Datei:ZD-939L Elektronik vorne.JPG|Umgebaute Elektronik </gallery> Der erste Test im noch auseinander gebauten Zustand spricht für Erfolg: die Soll-Temperatur ist bei 160 °C, die Ist-Temperatur bleibt bei 25 °C. Nach Kippen des Schalters klettert die Anzeige wie vorher nach oben. <gallery> Datei:ZD-939L Front umgebaut.JPG|Funktionstest mit ausgeschalteter Heizung </gallery> =J-EXT= Auf dem Board befinden sich noch zwei Vorhalte für Stiftleisten. Eine unbeschriftete (vermutlich zum Download der Firmware) und eine namens J-EXT. Rein aus Neugierde habe ich mir letztere etwas genauer angesehen, vielleicht spricht das Board ja mit einem. Die Leiterbahnen führen schon einmal alle zum Mikrocontroller, zusammen mit dessen Datenblatt lassen sich die Pins zuordnen. P3.x haben leider keine spezielle Peripherie zugeordnet, also eher unwahrscheinlich, dass da UART rauskommt. Möglich ist aber alles. Also Spannung mit dem Scope nachgemessen und nach positivem Befund den Logic-Analyzer angeschlossen: [[Datei:ZD-939L_Logic-Analyzer.png]] Aus den Daten lässt sich folgende Zuordnung ableiten: {| class="wikitable" |- ! Pin J-EXT !! Pin µC !! Pin-Name !! Funktion |- | 1 || - || - || +5V |- | 2 || 7 || P3.1 || ? |- | 3 || 9 || P3.3 || Clock |- | 4 || 10 || P3.4 || Data |- | 5 || - || - || GND |} Ein "Datenpaket" dauert etwa 2,6 ms und wird alle 20 ms gesendet. Allem Anschein nach werden die Daten in 16-Bit-Gruppen geschickt, zumindest bleibt der Clock nach 16 Bits immer ein bisschen länger High. Die Daten habe ich nicht genauer untersucht, da für mich der Reiz einfach nicht da ist. Wer es versuchen will, kann sein Glück mit meiner Aufzeichnung versuchen: [[Datei:ZD-939L J-EXT.zip]] Die Daten wurden mit Saleae Logic 1.1.18 Beta erstellt. Wenn ich mich richtig erinnere, war die Temperatur auf 160 °C Soll eingestellt und eine Ist-Temperatur von 25 °C (weniger macht das Teil anscheinend nicht) angezeigt. =Nachtrag 19.04.2015= Manfred hat sich etwas mehr Arbeit gemacht und und der Station zusätzlich noch eine Status-LED und eine niedrigere Stufe für den Luftdurchsatz hinzugefügt. Hier seine Beschreibung - vielen Dank dafür! <code> Jetzt habe ich endlich mal meine Heißluftstation bearbeitet. Etwas ange****t bin ich ja, dass da tatsächlich direkt mit Netzspannung geheizt wird, hätte ich nicht erwartet. Eigentlich kann da ein passender Schalter rein und fertig - aber, um das ordentlich zu machen, müsste ich die Kiste zerlegen, wegen Feilspänen, da habe ich keine Lust zu. Ich habe Deinen Vorschlag gegriffen und trenne die Steuerleitung. Gegen die Langeweile noch eine LED rein, weiße sieht man unter 1 mA schon leuchten. Im Gegensatz zur Beschreibung stehen da keine 5 V an der Steuerleitung, ich messe knapp 3,2 Volt. Wenn die leuchtet, ist also Abkühlphase! Die Luftmenge ist mir zu hoch, auah, am Drehpoti liegt Netzspannung. Das Ding hat 470 kOhm, mal einen R in Reihe probieren, bis gut 650 k liefert meine Pumpe noch Luft. Da ist jetzt ein weiterer Schalter drin, der 220 k in Reihe legt - eigentlich wäre auch ein 1 Meg-Poti mit parallel 2 MOhm klug, wenn es denn im Vorrat gewesen wäre. Vielleicht sollte dieser Punkt im Wiki ergänzt werden? Ich habe Kippschalter MTA-106 von Knitter eingesetzt, die können 250 Volt, haben aber keine VDE-Zertifizierung - von daher bin ich an der Stelle nicht ganz sauber. [...] Wie man sieht, sieht man an den Kippschaltern keine Mutter, Bastelei darf gerne auch anständig aussehen. Die Schalter haben Feingewinde, der Stahl vom Chinesengehäuse ist gut, also habe ich Gewinde geschnitten und von hinten gekontert. </code> <gallery> Datei:ZD-939L M Stromlauf_grau_1200.png|Stromlaufplan der Änderung Datei:ZD-939L M Detail_Schalter_1600_60.jpg|Änderungen von innen Datei:ZD-939L M Schalterfeld_1200_60.jpg|...und von vorne </gallery> =Siehe auch= * [http://hobbyelektronik.org/b/2014/05/eine-kleine-anmerkung-zu-chinesischen-namen/ Eine kleine Anmerkung zu chinesischen Namen] [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] ef6f3dd35fff82d3f4283c77875c6d9fa98ed821 1001 999 2015-05-26T18:53:01Z Chris 2 Neuer Nachtrag, Danke Manfred. wikitext text/x-wiki Vor geraumer Zeit hab ich mir eine Zhondi ZD-939L auf den Basteltisch gestellt. Diese Heißluftlötstation ist gerade beim Entlöten von SMD-Bauteilen ein sehr nützlicher Helfer. [[Datei:ZD-939L Hinweis.JPG|thumb|Aufkleber als Workaround]] Eines hat mich allerdings vom ersten Tag weg gestört: sie hat keinen Nachlauf zum Kühlen des Heizelements. Als "Workaround" hat der Importeur lediglich einen Hinweis angebracht, dass man vor dem Abschalten auf die Mindesttemperatur herunterdrehen und eine Minute warten solle. Mit dem Warten kann ich leben, allerdings ist das Einstellen der Temperatur etwas nervig: Minus-Taster drücken und halten und sich für jedes Grad einen Pieps anhören. Nur um beim Nächsten Einschalten genau das Gegenteil zu machen. selbstverständlich ebenfalls mit akustischer Untermalung. Dabei gibt es die Heißluft-Station (neben der Version mit Nachlauf) auch mit dienen Schalter fürs Heizelement. Warum hat das meine nicht? Es wird höchste Zeit, dass sich das ändert. =Analyse= [[Datei:ZD-939L_Innenleben.jpg|thumb|Blick auf die hintere Leiterkarte]] Auf das Ding und reingeschaut. Die Elektronik ist auf 3 Leiterkarten verteilt - hinten befindet sich ein teilbestücktes Board auf das die Netzleitung führt. Nachdem sich nichts darauf befindet, das auf Regelung hindeutet, dürfte es der Leistungsteil sein. Vorne im Gehäuse findet sich neben der Leiterkarte mit den Tastern vom Frontpanel auch die Platine mit dem Display. Die 3 schwarzen Vielbeiner darauf lassen erahnen: hier wird höchstwahrscheinlich geregelt. Heizung abdrehen könnte man nun sowohl auf der Leistungs- als auch der mutmaßlichen Reglerplatine. Man könnte natürlich auch direkt in die Leitung zum Heizelement eingreifen - aber warum sich die Finger an 230 V verbrennen, wenn man es auch einfacher und sicher haben kann? Ein genauerer Blick auf die Display-Platine kann also nicht schaden: <gallery> Datei:ZD-939L Regler.JPG|Die Reglerplatine </gallery> Der 8-beinige Chip links ist ein LM358, also ein Operationsverstärker. Beim mittleren Chip im TQFP-Gehäuse handelt es sich um einen Silabs C8051F310 - einem Mikrocontroller. Rechts im Bild befindet sich ein Holtek HT1621B. Holtek kennt man auch als Mikrocontroller-Hersteller - aber zwei Mikrocontroller für einen einfachen Regler? Nicht ganz. Der Holtek ist lediglich ein LCD-Controller, was auch die Leiterbahnen zu ihm erklärt. Die Regelung übernimmt alleinig der Silabs-Chip. Interessanter als die Regelung und das Display ist für den Umbau, über welche Anschlüsse die Heizung angesteuert wird. Drei der vier Stiftleisten sind mit der Platine hinten verbunden. Die 4-polige Stiftleiste links im Bild führt zur Taster-Platine und fällt damit schon mal weg. Die untere zweipolige Stifleiste ist ein Kandidat - nachdem sie aber verdächtig nahe am LM358, ein paar diskreten Bauteilen und einem Poti liegt, dürfte es sich um den Anschluss für den Temperaturfühler sein. Alle Leitungen außer dieser verbunden bestätigt den Verdacht: Keine Temperaturanzeige. Bleiben nur noch zwei. Die links obere sieht verdächtig nach Stromversorgung aus: etwas dickere Leiterbahnen, Dioden und Kondensatoren. Nicht zuletzt ein 78L05. Warum aber 3 Pins? Eingangsspannung, Masse und Ausgangsspannung? Nein, vermutlich handelt es sich um eine symmetrische Versorgung - entweder fürs Display oder den Operationsverstärker. Ein Blick in den hinteren Teil der Lötstation bestätigt es: Ein Trafo mit Mittelabzapfung. Die Heizung muss also von der Stiftleiste rechts oben angesteuert werden. Am Stecker hängen zwei Drähte, was die Sache leichter macht. Masse lässt sich durchpiepsen und damit ist auch der Ausgang gefunden. Muss nur noch geklärt werden, wann welche Spannung anliegt und ob man einfach so einen Schalter einbringen kann. Multimeter angehängt und den Aparillo losbrummen lassen: 5V, wenn die Heizung an ist. Um sicherzustellen, dass die 5V berührungssicher sind, schnell gegen das Gehäuse, das mit PE verbunden ist: 0V, also galvanisch getrennt. Ausgezeichnet! =Umbau= Ein Ort für den zusätzlichen Schalter ist schnell gefunden: Neben dem Hauptschalter ist noch Platz. Der Akkuschrauber leiert ein Loch in die Platte und der Schalter ist drin. Für die elektrische Verbindung habe ich die Leitung zum "Backpanel" aufgetrennt und den Schalter einfach eingefügt. Da ich die Schaltung dahinter nicht genauer ansehen wollte, habe ich mich für die sicherere Ansteuerung entschlossen - theoretisch könnte man einfach eine der Leitungen auftrennen und den Schalter einfügen. Allerdings bekommt dann die Schaltung "hinten" entweder das Signal vom Mikrocontroller oder floatet durch die Gegend. Da das nicht besonders toll ist, wechselt der Schalter zwischen dem ursprünglichen Pfad und Masse. So gibt es immer einen definierten Pegel und Probleme werden bestmöglich ausgeschlossen. <gallery> Datei:ZD-939L Elektronik vorne.JPG|Umgebaute Elektronik </gallery> Der erste Test im noch auseinander gebauten Zustand spricht für Erfolg: die Soll-Temperatur ist bei 160 °C, die Ist-Temperatur bleibt bei 25 °C. Nach Kippen des Schalters klettert die Anzeige wie vorher nach oben. <gallery> Datei:ZD-939L Front umgebaut.JPG|Funktionstest mit ausgeschalteter Heizung </gallery> =J-EXT= Auf dem Board befinden sich noch zwei Vorhalte für Stiftleisten. Eine unbeschriftete (vermutlich zum Download der Firmware) und eine namens J-EXT. Rein aus Neugierde habe ich mir letztere etwas genauer angesehen, vielleicht spricht das Board ja mit einem. Die Leiterbahnen führen schon einmal alle zum Mikrocontroller, zusammen mit dessen Datenblatt lassen sich die Pins zuordnen. P3.x haben leider keine spezielle Peripherie zugeordnet, also eher unwahrscheinlich, dass da UART rauskommt. Möglich ist aber alles. Also Spannung mit dem Scope nachgemessen und nach positivem Befund den Logic-Analyzer angeschlossen: [[Datei:ZD-939L_Logic-Analyzer.png]] Aus den Daten lässt sich folgende Zuordnung ableiten: {| class="wikitable" |- ! Pin J-EXT !! Pin µC !! Pin-Name !! Funktion |- | 1 || - || - || +5V |- | 2 || 7 || P3.1 || ? |- | 3 || 9 || P3.3 || Clock |- | 4 || 10 || P3.4 || Data |- | 5 || - || - || GND |} Ein "Datenpaket" dauert etwa 2,6 ms und wird alle 20 ms gesendet. Allem Anschein nach werden die Daten in 16-Bit-Gruppen geschickt, zumindest bleibt der Clock nach 16 Bits immer ein bisschen länger High. Die Daten habe ich nicht genauer untersucht, da für mich der Reiz einfach nicht da ist. Wer es versuchen will, kann sein Glück mit meiner Aufzeichnung versuchen: [[Datei:ZD-939L J-EXT.zip]] Die Daten wurden mit Saleae Logic 1.1.18 Beta erstellt. Wenn ich mich richtig erinnere, war die Temperatur auf 160 °C Soll eingestellt und eine Ist-Temperatur von 25 °C (weniger macht das Teil anscheinend nicht) angezeigt. =Nachtrag 19.04.2015= Manfred hat sich etwas mehr Arbeit gemacht und und der Station zusätzlich noch eine Status-LED und eine niedrigere Stufe für den Luftdurchsatz hinzugefügt. Hier seine Beschreibung - vielen Dank dafür! <code> Jetzt habe ich endlich mal meine Heißluftstation bearbeitet. Etwas ange****t bin ich ja, dass da tatsächlich direkt mit Netzspannung geheizt wird, hätte ich nicht erwartet. Eigentlich kann da ein passender Schalter rein und fertig - aber, um das ordentlich zu machen, müsste ich die Kiste zerlegen, wegen Feilspänen, da habe ich keine Lust zu. Ich habe Deinen Vorschlag gegriffen und trenne die Steuerleitung. Gegen die Langeweile noch eine LED rein, weiße sieht man unter 1 mA schon leuchten. Im Gegensatz zur Beschreibung stehen da keine 5 V an der Steuerleitung, ich messe knapp 3,2 Volt. Wenn die leuchtet, ist also Abkühlphase! Die Luftmenge ist mir zu hoch, auah, am Drehpoti liegt Netzspannung. Das Ding hat 470 kOhm, mal einen R in Reihe probieren, bis gut 650 k liefert meine Pumpe noch Luft. Da ist jetzt ein weiterer Schalter drin, der 220 k in Reihe legt - eigentlich wäre auch ein 1 Meg-Poti mit parallel 2 MOhm klug, wenn es denn im Vorrat gewesen wäre. Vielleicht sollte dieser Punkt im Wiki ergänzt werden? Ich habe Kippschalter MTA-106 von Knitter eingesetzt, die können 250 Volt, haben aber keine VDE-Zertifizierung - von daher bin ich an der Stelle nicht ganz sauber. [...] Wie man sieht, sieht man an den Kippschaltern keine Mutter, Bastelei darf gerne auch anständig aussehen. Die Schalter haben Feingewinde, der Stahl vom Chinesengehäuse ist gut, also habe ich Gewinde geschnitten und von hinten gekontert. </code> <gallery> Datei:ZD-939L M Stromlauf_grau_1200.png|Stromlaufplan der Änderung Datei:ZD-939L M Detail_Schalter_1600_60.jpg|Änderungen von innen Datei:ZD-939L M Schalterfeld_1200_60.jpg|...und von vorne </gallery> = Nachtrag 26.05.2015 = Mittlerweile gibt es beim Ramschmax auch eine Version mit [http://www.pollin.de/shop/dt/MjM4OTUxOTk-/Werkstatt/Loettechnik/Loetgeraete/Heissluft_Loetstation_mit_LCD_ZD_939L_4_Wechselduesen.html fertig eingebautem Kühlschalter]. =Siehe auch= * [http://hobbyelektronik.org/b/2014/05/eine-kleine-anmerkung-zu-chinesischen-namen/ Eine kleine Anmerkung zu chinesischen Namen] [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] b4ef9cc800c247a7183360e10b23fe4bc583b5a1 EMR7370 0 287 1002 743 2015-05-26T18:55:58Z Chris 2 Typo in URL korrigiert wikitext text/x-wiki [[Datei:EMR7370_aussen.jpg|thumb|Empfänger]] Vor einer Weile bin ich durch Kundenwerbung beim [http://www.pollin.de "Ramschmax"] an einen Funk-Energiekosten-Messgerät [http://www.pollin.de/shop/dt/MTk2OTYxOTk- EMR7370] gekommen. Da das Teil nicht unbedingt durch [http://hobbyelektronik.org/b/?p=540 Qualität] überzeugte, lag es eine gute Weile in der Schublade. Nachdem ich nach den Klausuren wieder etwas Zeit hatte und die Neugier doch siegte, landete es doch wieder auf dem Tisch. =Schaltungsanalyse= Der erste Schritt zur Analyse des Ganzen führt natürlich über den Schraubendreher. Im Inneren befindet sich eine große Leiterplatte, auf der eine kleinere Huckepack sitzt. Da an dieser eine Antenne angelötet ist, ist der Funkempfänger schnell gefunden. Der Silkscreen verrät sogar die Anschlussbelegung desselben. Nachdem bei der ersten Untersuchung die Hälfte der Beschriftung durch das Modul verdeckt war, habe ich diese nochmal weiter oben angebracht, deswegen bitte nicht wundern. Auch die Buchsen- & Stiftleiste sind nicht original, sondern von mir hinzugefügt. Da die andere Seite der Leiterplatte nicht spektakulärer ist, habe ich auf ein Foto verzichtet. Das einzig halbwegs interessante ist ein I²C-EEPROM, dessen Takt- und Datenleitung an der Stiftleiste liegt. <gallery> Datei:EMR7370_bottom.jpg|Platinenunterseite Datei:EMR7370_RXM01.jpg|Funkmodul RXM01 </gallery> Zu dem Funkmodul konnte ich im Internet nur die Bestätigung über die Existenz finden, wobei dort selbst die Angabe der Betriebsspannung unterschiedlich war. =Protokollanalyse= Da die Leiterplatte mit den Bezeichnungen SCK/SDI/SDO/NSEL schon auf SPI hindeutet wusste ich ungefähr, worauf ich mich einlasse. Mit der Stift- und Buchsenleiste zwischen Funkmodul und Hauptplatine sollte es relativ einfach sein, auf dem untersten Layer (Bitübertragungsschicht, wenn man es an dieser Stelle so nennen will) zu analysieren. Also Probes angeschlossen und gleich mal den neuen Logic Analyzer getestet. Die erste Messung zeigt die übertragenen Daten vom Einschalten des Empfängers bis zur ersten Anzeige der Messwerte. Genauer betrachtet und mit aktiviertem SPI-Analyzer sieht man auch, was übertragen wird: <gallery> EMR7370_LA1.png|Übersicht EMR7370_LA2.png|Zoom auf den ersten Block </gallery> == Initialisierung == Zur mutmaßlichen Initialisierung werden folgende Daten übertragen: <pre> 0x90D9 0xA67C 0xC080 0xC081 (500ms Pause) 0xCE85 0xCE87 0xC4AB 0xC823 0xC6C7 0xB014 0xC205 0xC080 (188ms Pause) 0xC081 (4ms Pause) 0x94D9 0xC209 (5ms Pause) 0x00 0x90D9 0xC080 (52ms Pause) 0xC081 </pre> Auch nach dem Empfang eines Datenpaketes sendet die Elektronik noch ein paar Päckchen an den Empfänger: </pre> 0xCE85 0xC080 (längere Pause) 0xC081 (3ms Pause) 0xCE85 0xCE87 </pre> Hier fällt auf, dass 0xC080 und 0xC081 oft in Kombination (siehe auch oben) und vor allem in der Nähe eines Datenempfangs auftreten. Ob dahinter ein Zusammenhang steckt?!? Da ich mich schon einmal kurzzeitig mit Funkmodule aus dem Hause HopeRF auseinandergesetzt habe und deren Produkte eine ähnliche Bezeichnung haben (z. B. RFM01), habe ich auf gut Glück auf deren Homepage nochmal vorbeigeschaut. Wie durch meine vorherige Recherche erwartet, fand ich nichts, was genauso hieß oder aussah wie mein Funkmodul, allerdings blieb ich kurz am Datenblatt des RFM01 hängen. Nachdem ich ein paar der Befehle in Hex umrechnete, stellte sich ein deutlicher Wiedererkennungswert heraus! Alle (bis auf einen) der gesendeten Datensätze ließen sich sinnvoll durch die Inhalte des Datenblatts rekonstruieren - also ein voller Erfolg. Im Endeffekt ändert es nichts daran, dass die Portierung auf den AVR auch so funktionierte, allerdings hilft die Bedeutung der gesendeten Befehle deutlich, das zu verstehen, was man macht. ==Datenpaket== [[Datei:EMR7370_LA3.png|thumb|Datenempfang (großer Monitor erforderlich)]] Die eigentliche Datenübertragung wird durch das Interrupt-Signal NIRQ angestoßen. Das N deutet auf "negative", also einer negativen Flanke hin, was auch der Messung entspricht. Nach dem Interrupt muss zunächst ein Nibble gelesen werden, das den Datenempfang signalisiert. Anschließend kann ein vollständiges Byte an SDO (Serial Data Out - aus Sicht de Funkmoduls) bzw. MISO (Master In Slave Out) eingelesen werden. Da die Schnittstelle bitseriell ist, ist auch die Flanke sowie die Reihenfolge der Bits wichtig. In diesem Fall wird zur steigenden Flanke von SCK (Serial Clock) gelesen, während sich die Daten zur fallenden Flanke ändern. Auch wird hier das MSB (Most Significant Bit) zuerst übertragen (was auch der üblichen Leseweise von Bits entspricht). Anzumerken ist bei dem Empfänger, dass man wissen muss, wie viele Byte empfangen werden sollen. Hier sind schon sehr viele (inklusive mir) hereingefallen. Sofern das Modul dem Verhalten derer von HopeRF entspricht, wird die Übertragung durch ein Synchronisationswort angestoßen, aber nicht signalisiert, wann die Übertragung zu Ende ist. Heißt: Der Empfänger weiß zwar, wann der Sender angefangen hat, aber nicht, wann er wieder aufhört. Das ist dann Protokollsache. Weiß man also nicht, wann das Paket zu Ende ist, wird man es im dümmsten Fall auch nie merken, da der Empfänger einfach das Rauschen auf dem Kanal auswertet. Das dient aber aller höchstens als Zufallsgenerator. Wie unten in der Tabelle zu sehen, umfassen die Pakete eine Länge von 12 Bytes. Danach muss man selber den Empfänger zum Schweigen bringen bzw. zurücksetzen. ==Anmeldung== Zur Anmeldung eines Senders am Empfänger muss die Verbindungs-Taste länger gedrückt werden, danach wird immer wieder 0x25 0x2A, die Adresse (2 Byte) sowie (vermutlich) eine Prüfsumme gesendet. Da die Anmeldung zum Betreiben eines eigenen Empfängers nicht erforderlich ist, behandle ich diese nicht weiter. =Datenanalyse= Für die Datenanalyse erzeugte ich mir durch eine definierte Last (vulgo: Glühlampe) Werte, die ich in Excel zwischen den gesendeten und auf dem EMR angezeigten Werten abglich. Hier eine kleine Tabelle einiger Werte: {| class="wikitable sortable" |- ! U !! I !! P !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 !! 9 !! 10 !! 11 |- | 220,0 || 0,00 || 0,0 || 25 || 6A || 54 || 72 || 40 || 00 || 00 || 00 || BC || 40 || 00 || 6F |- | 222,0 || 0,05 || 0,0 || 25 || 6A || 54 || 72 || 40 || 00 || 00 || 38 || BC || 40 || 00 || 37 |- | 221,0 || 0,26 || 58,0 || 25 || 6A || 54 || 72 || 40 || 74 || 01 || 0C || BA || 40 || 00 || F0 |- | 222,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 07 || BD || 40 || 00 || F1 |- | 221,5 || 0,26 || 58,5 || 25 || 6A || 54 || 72 || 40 || 75 || 01 || 06 || BB || 40 || 00 || F4 |- | 221,5 || 0,17 || 39,0 || 25 || 6A || 54 || 72 || 40 || 4E || 00 || B1 || BB || 40 || 00 || 71 |- | 222,5 || 0,17 || 39,5 || 25 || 6A || 54 || 72 || 40 || 4F || 00 || B2 || BD || 40 || 01 || 6C |- | 222,5 || 0,06 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 43 || BD || 40 || 01 || 25 |- | 223,0 || 0,03 || 2,5 || 25 || 6A || 54 || 72 || 40 || 05 || 00 || 25 || BE || 40 || 01 || 42 |- | 222,0 || 0,03 || 2,0 || 25 || 6A || 54 || 72 || 40 || 04 || 00 || 20 || BC || 40 || 01 || 4A |- | 222,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3E || BD || 40 || 01 || 2D |- | 223,5 || 0,06 || 1,0 || 25 || 6A || 54 || 72 || 40 || 02 || 00 || 3C || BF || 40 || 01 || 2D |- | 222,5 || 0,31 || 29,0 || 25 || 6A || 54 || 72 || 40 || 3A || 01 || 3E || BD || 40 || 01 || F4 |- | 222,0 || 0,37 || 42,0 || 25 || 6A || 54 || 72 || 40 || 54 || 01 || 74 || BC || 40 || 01 || A5 |- | 223,0 || 0,35 || 42,5 || 25 || 6A || 54 || 72 || 40 || 55 || 01 || 66 || BE || 40 || 02 || AF |- | 221,5 || 0,19 || 38,0 || 25 || 6A || 54 || 72 || 40 || 4C || 00 || BF || BB || 40 || 02 || 63 |- | 224,0 || 0,13 || 12,5 || 25 || 6A || 54 || 72 || 40 || 19 || 00 || 8B || C0 || 40 || 03 || C4 |} Die ersten drei Spalten geben die Spannung in Volt, den Strom in Ampere sowie die Leistung in Watt an, alle weiteren die empfangenen Bytes im Hex-Format. Ziel der Tabelle ist es, Muster zu erkennen und die Bytes den Werten zuzuordnen. Dabei hilft es natürlich Messungen zu erzeugen, bei dem möglichst viele Werte konstant sind und sich nur einer verändert. Beim Strom bzw. der Leistung klappt das gut, bei der Spannung ist man ohne Trenntransformator etwas auf Netzschwankungen angewiesen. Wer es selber einmal probieren will, kann die Tabelle mit einem Klick auf die Spaltenköpfe sortieren. ==Spannung== Sortiert man z. B. nach der Spannung sieht man relativ schnell, dass diese einen Zusammenhang mit Spalte 8 hat. Anhand der übertragenen und der abgelesenen Werte kann man nun den Zusammenhang ermitteln. In der Regel ist dieser sehr einfach zu berechnen, solange er linear ist. Mathematisch kann man die Formel <math> x=a \cdot y + b </math> in einem Gleichungssystem mit den verschiedenen Werten einsetzen, wobei x der gemessenen Spannung und y dem übertragenen Wert entspricht - was natürlich auch anders herum funktioniert. Mit ein wenig Zahlengefühl muss man keine Gleichungssysteme lösen. Nimmt man die Spannungen 222,0V 222,5V und 223V und die korrespondierenden Werte 0xBC, 0xBD und 0xBE (bzw. den dezimalen Entsprechungen 188, 189 und 190) sieht man, dass die Nachkommastelle der niederwertigsten Stelle entspricht. Teilt man durch 2, bekommt man 94; 94,5 und 95 - die Differenz zu den abgelesenen Spannungen entspricht 128. Das passt auch für alle anderen Werte. ==Leistung== Die Unterscheidung zwischen Strom und Leistung ist schon etwas schwieriger. Zu meinem Glück (und warum auch immer) habe ich bei einem Messwert eine Leistung von 0W und gleichzeitig einen Strom > 0A erfasst. Sucht man zugleich die Spalten mit zur Leistung korrespondierenden Werten heraus, kommt man auf Spalte 4 und 5, wobei in Spalte 4 das 7. Bit ignoriert werden muss. Ein Gleichungssystem muss man auch hier nicht ansetzen, da die angezeigte Leistung sich nur in 0,5-Schritten ändert, ist wie bei der Spannung anzunehmen, dass man den empfangenen Wert nur durch 2 teilen muss. ==Strom== Ab hier ist nun langsam eine Auswahl durch Ausschlussverfahren möglich. Die Werte zwischen Leistung und Spannung in (Spalte 6 und 7) umgewandelt und siehe da - der Strom in mA. Bei genauerem Hinsehen fällt auf, dass der angezeigte Strom im Empfänger nicht richtig gerundet, sondern nur abgeschnitten wird. ==Adresse== Die Adresse findet man am leichtesten heraus, wenn man beide Sender gleichzeitig betreibt. Was in der Tabelle oben nicht zu sehen ist, zeigt sich mit dem Logic Analyzer sehr schnell - Spalte 2 und 3 dienen der Adressierung. ==Geräteklasse (?)== Die ersten beiden Bytes haben sich bei keinen der empfangenen Pakete (außer bei der Anmeldung) unterschieden, daher gehe ich davon aus, dass es sich dabei lediglich um eine Identifikation der Geräteklasse handelt oder zumindest um eine Synchronisation auf höherer Ebene handelt. ==Energie== Auffällig am Empfänger ist, dass dieser auch nach einem Reset über die genutzte Energie der letzten Tage Bescheid "wusste". Die zugehörigen Werte stehen in Spalte 9 und 10, wobei auch hier wieder ein Offset von 0x4000 bzw. 16384 zu verzeichnen ist. Die Skalierung ist hierbei etwas krumm, geteilt durch 100 ergibt sich die Energie in kWh, somit wird intern in 10Wh-Schritten gezählt. ==Prüfsumme== Da es sich um eine Funkübertragung handelt, ist eine Prüfsumme Pflicht. Um speichersparend zu arbeiten, wird diese in der Regel on-the-fly berechnetund am Ende gesendet. Mit dem CRC8-Code des [[VBus-Decoder]]s hatte ich auf Anhieb Erfolg. ==Zusammenfassung== {| class="wikitable" |- ! Wert !! MSByte !! LSByte !! Offset !! Faktor !! Bemerkung |- | Klasse || 0 || 1 || -- || -- || keine anderen Werte bekannt |- | Adresse || 2 || 3 || -- || -- || |- | Leistung || 4 || 5 || 0x4000 || 0,5 || W |- | Strom || 6 || 7 || 0x0000|| 0,001 || A |- | Spannung || 8 || -- || 0x0000 || 0,5 || V |- | Energie || 9 || 10 || 0x4000 || 0,01 || kWh |- | Prüfsumme || 11 || -- || -- || -- || CRC aller vorangegangenen Bytes |} =Client= {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = D1 | FuseL = F8 }} Der nächste Schritt ist natürlich einen eigenen Client zu programmieren. Verwendet habe ich hierzu den mittlerweile doch etwas betagten ATmega8, der jedoch nach wie vor seinen Zweck erfüllt. Um es einfach zu halten habe ich das SPI-Interface im Bitbanging-Mode geschrieben, wobei auch die benötigten Pausen (vom Original übernommen) womöglich etwas vorsichtig gewählt sind. Ich halte jedoch niemanden ab, das Timing zu optimieren. Die Software führt zunächst eine Initialisierung der Hardware durch und überprüft dann im Main-Loop, ob ein vollständiges Datenpaket empfangen wurde. Ist dies der Fall, wird das Paket dekodiert und bei Erfolg in an den entsprechenden Speicherplatz geschoben. Ohne höheren Debug-Level muss man die Adressen der jeweiligen Sender vorher setzen, sonst sieht man nichts. Standardmäßig werden die Messdaten alle 10 Sekunden ausgegeben, wird 30 Sekunden nichts empfangen, wird der Empfänger neu initialisiert, wobei ich damit noch etwas unzufrieden bin: Während Flashen des AVRs ist es immer wieder passiert, dass der Empfänger den Interrupt gesetzt hat, dieser aber nicht abgearbeitet wurde. Das hat zur Folge, dass der Empfang auch nach erneutem Initialisieren einfach nicht funktioniert. Da das Funkmodul keinen Reset-Eingang hat, hilft hier entweder eine bessere Behandlung des Interrupts oder die die Versorgung des Empfängers über den Mikrocontroller zu schalten. Letzteres ist zwar nicht elegant, dafür aber effektiv. Eine der beiden Methoden müsste zur Erhöhung der Zuverlässigkeit noch implementiert werden. Die Pinbelegung des Funkmoduls ist der Datei RFM01.h zu entnehmen. Die Ausgabe der Daten erfolgt am UART mit 57600 Baud 8N1. =Download= * [[Datei:EMR7370.zip]] LA-Aufzeichnungen (mit [http://www.saleae.com/downloads Saleae Logic] einsehbar), Excel-Datei mit ausgewerteten Beispieldatensätzen, Beispielcode ATmega8 (AVR-Studio 5) b2b466fe2f15bb6c3bfc12f0b6d77de1dccaa2ac Datei:Apds9300.zip 6 418 1013 2016-01-02T14:28:56Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Apds9300 asy.jpg 6 419 1014 2016-01-02T14:29:10Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Apds9300 box.jpg 6 420 1015 2016-01-02T14:29:19Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Apds9300 brd.png 6 421 1016 2016-01-02T14:29:29Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Apds9300 diag 1 1.png 6 422 1017 2016-01-02T14:29:34Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Apds9300 diag 1 2.png 6 423 1018 2016-01-02T14:29:40Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Apds9300 diag 2 1.png 6 424 1019 2016-01-02T14:29:52Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Apds9300 diag 2 2.png 6 425 1020 2016-01-02T14:29:57Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Apds9300 diag 2 3.png 6 426 1021 2016-01-02T14:30:08Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Apds9300 sch.png 6 427 1022 2016-01-02T14:30:15Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Lichtsensor Avago APDS-9300 0 428 1023 2016-01-02T14:30:34Z Chris 2 Seite erstellt wikitext text/x-wiki Vor einiger Zeit (genau genommen noch im Studium) wollte ich mit Lichtsensoren (ambient light sensors, ALS) spielen. Da ich bei Farnell bestellen konnte, kamen zwei Avago APDS-9300 mit auf das Bestellformular (Mittlerweile auch beim blauen Claus bzw. Völkner zu haben). Aufgrund der Bauform und Zeitmangel blieben sie relativ lange in der ESD-Tüte. =Der Sensor= Was soll man groß Worte über einen Lichtsensor verschwenden? Licht rein, aufbereitetes Signal raus und gut ist. Ganz so einfach ist es (zumindest beim APDS-9300) leider nicht. Viele optische Sensoren drehen bei Infrarot wild, das menschliche Auge zeichnet sich dagegen als ziemlich unempfindlich aus. In Digitalkameras werden aus diesem Grund IR-Filter verbaut (die Astrofotografen wieder entfernen), allerdings scheint das den Entwicklern bei Avago entweder zu teuer oder zu unpraktisch gewesen zu sein - sie haben zwei Fotodioden verbaut: Eine ist empfindlich auf das sichtbare Licht und Infrarot, die andere nur auf Infrarot (siehe Seite 7 vom Datenblatt). Der Rest ist Mathematik. Da die menschliche Wahrnehmung weitestgehend logarithmisch ist, braucht man zur Nachbildung einen großen Dynamikumfang. Daher kann der ALS mehrere Betriebsmodi. Zum einen kann man die Integrationszeit (also die Zeit, in der die Lichtdosis gesammelt wird) wählen - konkret zwischen 13,7 ms, 101 ms und 402 ms. Zum anderen kann man einen 16-fach-Verstärker zuschalten. Dadurch gewinnt man zwar Empfindlichkeit, bezahlt die aber mit der Auflösung und Rauschen. Die Wahl der richtigen Einstellung hängt selbstverständlich von der Umgebungshelligkeit ab, ansonsten liest man entweder 0 oder der bekommt Werte in der Sättigung, die einfach keinen Sinn ergeben. =Hardware= Bei der Fertigung meiner ersten Fuhre Leiterkarten bei DirtyPCBs landete auch ein kleines Breakout-Board auf dem Panel: <gallery> Datei:apds9300_sch.png|Schaltplan, Datei:apds9300_brd.png|Layout Datei:apds9300_asy.png|und aufgebautes Sensormodul </gallery> Neben dem Sensor selbst befindet sich aufgrund dessen etwas unpraktischen Versorgungsspannung ein 2,5 V-LDO-Spannungsregler. Die Wahl auf den LDO fiel, damit die Schaltung neben den eher altmodischen 5 V auch bei 3,3 V (und somit zum Beispiel mit dem Raspberry Pi) funktioniert. Als Schnittstelle dient bei dem Lichtsensor I²C, die Treiberstufen sind hier zwar zwangsläufig Open Drain und können deshalb in aller Regel etwas höhere Spannungen als die Betriebsspannung ab, bei den Eingangstufen bzw. ESD-Schutz wird es für das Bauteil bei höheren Spannungen ungemütlicher. ==Levelshifter== Damit man den I²C mit höherer Spannung betreiben kann, wird ein (bzw. eher zwei) Levelshifter benötigt. Diesen kann man entweder fertig kaufen oder mit nur wenigen Bauteilen aufbauen - [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] erklärt, wie es funktioniert. Für alle, die zu faul zum Klicken oder des Englischen nicht ganz so mächtig sind: Bei der Schaltung wird sowohl die Body-Diode als auch die schaltende Wirkung des FET genutzt (und als Beifang die Pull-Up-Widerstände, die man für I²C eh braucht). Das Schaltungsprinzip ist einfach wie genial: Wird keine der beiden Seiten auf Masse gezogen, ist U_GS nahezu 0 oder zumindest weit unter U_GS,th - der FET sperrt und dadurch dass die Spannung auf der Kathoden-Seite der Diode höher als auf der Anoden-Seite ist, sehen sich die Schaltungsteile nicht. Den Rest erledigen die Pull-ups. Wird auf der 3,3 V-Seite das Signal auf Masse gezogen, steigt U_GS über U_GS,th und der Transistor beginnt zu leiten. Dadurch sieht man auf der 5 V-Seite die Masse der 3,3 V-Seite. Szenario Nummer 3 ist nicht ganz so offensichtlich: Wird die 5 V-Seite auf Masse gezogen, fällt zunächst der Drain-Pin des FETs auf Masse. Jetzt kommt ein Teil vom Transistor ins Spiel, der einem manchmal einen Knoten ins Gehirn macht: Die Body-Diode. Ist auf deren Kathoden-Seite ein niedrigeres Potenzial als auf deren Anoden-Seite, wird sie leitfähig, somit zieht sie den Source-Pin ebenfalls gegen die Masse, die auf der Source-Seite anliegt. Gegen - nicht auf - da noch ein bisschen Vorwärtsspannung abfällt. Allerdings fällt steigt auch U_GS über U_GS,th (der zweite Knoten im Gehirn) und der FET wird leitfähig. Somit ist die Masse der 5 V-Seite auf der 3,3 V-Seite (relativ) sauber sichtbar. Fertig ist der pillepalle einfache bidirektionale Levelshifter. Einziger Nachteil: die Spannung "links" muss immer kleiner sein als die "rechts". Zudem ist man mit den Spannungspegeln begrenzt (zum einen durch U_GS,th des FET und zum anderen durch die U_f der Body-Diode). Übrigens kann man durch das Abklemmen des Gates die Seite mit der niedrigeren Spannung isolieren. =Software - der erste Versuch= Wie kann man relativ einfach mit I²C basteln? Bei denen im PC kommt man zumindest unter Windows nicht ran (und will es [http://www.paintyourdragon.com/?p=43vermutlich auch nicht]), bei Mikrocontrollern muss man erst Soft- und Hardware basteln - das ist aufwändig und fehleranfällig. Was liegt also näher, als den Raspberry Pi zu verwenden? Dort gibt es neben den [https://github.com/groeck/i2c-tools i2c-tools] auch eine Integration in Python. Da ich keine besonderen Erfahrungen mit letztere Sprache habe, möge man mir die Codequalität entschuldigen. apds9300.py ist eine Klasse, die die Kommunikation mit dem Sensor beinhaltet. Mit viewapds.py wird der Sensor im Halbsekunden-Takt ausgelesen und sowohl die rohen als auch der berechnete Wert ausgegeben. So viel zur Theorie. In der Praxis verwandelte sich die Verwunderung sehr schnell in Verzweiflung - es kamen einfach keine auch nur halbwegs sinnvollen Werte heraus. Zuerst hatte ich meine kläglichen Versuche in Python im Verdacht, nach mehrmaligem Überprüfen und neu schreiben stellte sich allerdings heraus, dass anscheinend etwas mit dem Chip oder Datenblatt nicht passt, denn ein Vergleich mit [[wpde:Lux_(Einheit)#Beispiele_typischer_Beleuchtungsst.C3.A4rken typischen Werten]] in Wikipedia sagte mir nur: du liegst falsch. Nach ein paar Recherchen stellte sich heraus, dass der APDS-9300 auf einem anderen Sensor basiert (oder zumindest nicht verleugenbare Ähnlichkeiten besitzt), dem TS256x von TAOS. Auch der physische Aufbau hat gewisse Ähnlichkeiten (und die Formeln zur Berechnung der Helligkeit ebenfalls). Zudem hatten auch schon andere das Problem mit den Berechnungen, nur gab es keine Lösung. =Kalibrierung= Da hilft nur noch eines: Kalibrieren. Nur gegen was? Die Helligkeitswerte aus dem oben erwähnten Wikipedia-Artikel kann man nicht so einfach und vor allem nicht so genau nachstellen, also muss entweder eine kalibrierte Lichtquelle her oder Vergleichsmessungen gemacht werden. Es liegen ja genügend "Messgeräte" in Form von Handy und Tablet herum. Mit einer [https://play.google.com/store/apps/details?id=com.notquitethem.android.luxmeter passenden App] bekommt man die Helligkeit mundgerecht angezeigt, nur: bei meinen HTC (Sensation, Flyer und [http://hobbyelektronik.org/b/2013/02/transplantation-geglueckt-patient-muss-sterben/ Explorer]) kann man nur zwischen heller Sommertag, bedeckter Sommertag und Zappenduster unterscheiden. Das LG-Handy war in der interessanten Zeit in Reparatur und das Samsung-Tablet hatte zwar eine sehr hohe Auflösung aber dafür eine völlig unbrauchbare Winkelabhängigkeit. Ich habe mir sogar überlegt, mit der Fotokamera zu messen. Aber wie zum Henker kommt man von Blende, Belichtungszeit, Bildempfindlichkeit und Bildausschnitt auf einen brauchbaren Helligkeitswert in Lux? Nachdem die Granularität durch die festen Schritte bei den drei ersten Parametern recht schlecht ist und die Messung durch den Bildausschnitt noch heikler wird, habe ich es bei der Idee belassen. Es muss also ein geeignetes Messgerät her. Nur für das Vermessen eines Sensors Messequipment kaufen (das den Sensor auch gleich ersetzt)? Muss nicht sein: ==Minolta T-10== In der Arbeit ist u. a. ein portables Luxmeter vorhanden und ich durfte es mir freundlicherweise für zwei Wochenenden ausleihen. Das Teil hat eine RS-232-Schnittstelle, wenn auch mit einem etwas komischen Stecker. Nach der Protokollbeschreibung muss man etwas suchen, allerdings ist die Implementierung (abgesehen vom etwas verschwurbelten Ausgabeformat) relativ einfach zu bewerkstelligen. Wer in die Verlegenheit kommt, so ein T-10 (oder vergleichbare Modelle) auszulesen: unten in den Downloads gibt es sowohl für Python als auch C# Quelltexte. ==Versuch 1== Der Messaufbau umfasst: * ALS und Luxmeter (über USB-RS232-Wandler) am Pi * eine windig zusammengebaute Lichtquelle aus LED-Streifen, Kühlkörper und Diffusor aus einem alten Notebook-Display. * Ein Rigol DP832 als Spannungsquelle * Eine Metallschiene sowie ein Pappkarton zum Aufbauen eines "Lichtgalgen" Beide Lichtsensoren (Minolta und mein Kalibrierkandidat) wurden auf gleiche Ebene gebracht (wichtig!) und fixiert. Das Netzteil kann Spannungs- und Stromsweeps, die für solch einen Zweck auf den ersten Blick perfekt geeignet sind. Also den Strom von 0 bis IIRC knapp 1,5 A in 400 Schritten zu je 2 Sekunden durchlaufen lassen, das Messgerät und Sensor mit etwas höherer Frequenz abfragen und in eine Log schreiben lassen. Das Ganze mit allen möglichen Konfigurationen des ALS. Excel auf dem großen PC macht den Rest. Naja, denkste. Die Helligkeit ging alles andere als linear hoch. Die Daten habe ich direkt weggeworfen und die Messung erneut mit Variation Spannung laufen lassen - entgegen dem allgemeinen Glauben ging die Helligkeit linear hoch. Trotzdem ist und bleibt die Regel: LEDs über Stromquellen versorgen. Die Gründe breite ich hier jetzt nicht aus. Dort die beiden Helligkeitswerte im X-Y-Diagramm auftragen lassen und feststellen, dass der Sensor fernab von dem ist, was zu erwarten ist. Genauso sind die Daten in der Hinsicht etwas ungeschickt zum Auswerten, dass es für jede tatsächliche Helligkeit mehrere Wertepaare gibt. Gleichzeitig gibt es aber auch (erwartungsgemäß) ungültige Wertpaare, da ein Sensor vor und der andere nach dem Umschalten der Spannung ausgelesen wurde. Die ganzen Messartefakte kann man zwar filtern, aber das ist unnötig und nervig. Nachdem die ganzen Messungen durch waren, musste das Luxmeter auch schon wieder zurück in die Arbeit. Nachdem der erste Lauf vielversprechend war, glaube ich, dass die anderen Messungen ok waren. Zudem war es viel zu heiß (Sommer 2015), um im Büro zu sitzen. Long story short: ein kleiner Programmierfehler und die Integrationszeiten wurden nicht in den Sensor geschrieben. <gallery> Datei:apds9300_diag_1_1.png|Verstärkung = 1; Integrationszeit = 13,7ms Datei:apds9300_diag_1_2.png|Verstärkung = 16; Integrationszeit = 13,7ms </gallery> Aarrgghh! ==Versuch 2== Fehler darf man machen, solange man daraus lernt. Das Rigol kann USB, und für das Auslesen des ALS habe ich eine Schaltung mit dem [http://hobbyelektronik.org/b/2015/09/mcp2221/ MCP2221] aufgebaut. Die Lichtquelle bleibt die selbe, sie steckt aber nun in der Decke eines Schuhkartons. Dadurch kann der Abstand, Position und Helligkeit (Streulicht!) relativ gut definiert werden: <gallery> Datei:apds9300_box.png|Aufbau der Messbox </gallery> Software: Dieses Mal in C#. Das kenne ich halbwegs und mag es. ===Automatisierung=== Zur Ansteuerung vom Netzteil muss erst einmal [https://www.ni.com/visa/ NI VISA] installiert werden. Ich hasse es, ich liebe es. Ich hasse es, weil die VISA-Treiber ein riesiges Bollwerk sind und man beim ersten Versuch immer die falschen erwischt. Zudem gibt es einen schönen Bug, bei dem Windows nach deren Installation irgendwann anfängt, knapp 20 Minuten für den Login zu braucht. Den [http://digital.ni.com/public.nsf/allkb/814FEF952915137686257B6B006C5F4F?OpenDocument offiziellen Fix] habe ich selbst noch nicht getestet, mit der im [http://forums.ni.com/t5/LabVIEW/Issues-with-windows-7-after-Labview-2012-installation/m-p/2257858#M715816 NI-Forum] beschriebenen Vorgehensweise habe ich gute Erfahrungen gemacht. Dadurch macht man sich unter Umständen zwar [[wpde:LAN eXtensions for Instrumentation|LXI]] kaputt, was in den meisten Fällen eh nicht verwendet wird. Was ich an VISA liebe? [[wpde:SCPI]]! Messautomatisierung ist etwas wirklich feines und nicht nur, weil man auf dem Weg in die Mittagspause noch kurz "MAHLZEIT" auf dem Multimeter anzeigen lassen kann. Mir hat es in der Arbeit bereits unbeschreiblich viel manuelle Messzeit erspart. Dazu kommt, dass die Wiederholbarkeit sehr gut ist. Wie auch immer, die Software ist schnell und hässlich - aber zweckmäßig - runtergerissen. Die Messungen sind zum Einstellen der Helligkeit der Lichtquelle synchronisiert und neben den deutlich besseren Ergebnissen kann ich zugleich meine Lichtquelle kalibrieren. Ein Messlauf dauert nicht ganz zwei Minuten, wegen der unterschiedlichen Integrationszeiten und den beiden möglichen Verstärkungsfaktoren mal 6 und schon hat man einen Sensor vermessen. ==Auswertung== Das ganze nochmal in Excel verwurstet und es sieht gar nicht mal so gut aus: <gallery> Datei:apds9300_diag_2_1.png|Messergebnisse 1. Sensor mit Gain = 1 Datei:apds9300_diag_2_2.png|Messergebnisse 1. Sensor mit Gain = 16 </gallery> Im ersten Diagramm sieht man, dass die Werte schön und nahezu linear nach oben gehen, allerdings ist da - je nach Integrationslänge ordentlich Faktor drauf. Bei der Ausgabe wurde die Integrationszeit nicht berücksichtigt. Die Einbrüche im zweiten Diagramm lassen sich durch die tatsächlichen Messwerte erklären: <gallery> Datei:apds9300_diag_2_1.png|Messwerte ohne und 16-facher Verstärkung </gallery> Kanal 0 geht bei 16-facher Verstärkung sehr früh in Sättigung - das ist alles. Ok, nun müssen die Helligkeitswerte noch richtig skaliert werden. Meine Vermutung geht stark in die Richtung, dass entweder die Lichtempfindlichkeit oder die Integrationszeit bei den Sensoren nicht ganz richtig sind. Man kann den Korrekturfaktor zwar auf die berechnete Helligkeit anwenden - dadurch dass es in den Berechnungen keine Offsets gibt, sollte das auch funktionieren. Mir ist es allerdings deutlich lieber, direkt die rohen Werte zu behandeln. Also die Messwerte skalieren, durch die Formel zur Berechnung der Helligkeit jagen und das Ergebnis vergleichen. Excel kann das relativ gut automatisch - mit der Zielwertsuche. Der Parameter dafür ist die prozentuale Abweichung der berechneten Helligkeit und der Referenzmessung vom Luxmeter. Damit das Ganze funktioniert, muss der Algorithmus zur Berechnung in Excel implementiert werden. Ich habe aufgehört zu zählen... Unter Berücksichtigung der Integrationszeiten ergibt sich ein Faktor von relativ genau 0,2, um auf die "richtige" Helligkeit zu kommen. Zum Vermessen des zweiten Sensors habe ich diesen Faktor für die Berechnung des ausgegebenen Wertes in meine Software eingetragen und es kommt relativ gut hin - über den kompletten Messbereich war die Abweichung nicht größer als 5 %. Selbstverständlich ist das statistisch nicht aussagekräftig aber trotzdem eine Bestätigung, dass die ganze Aktion nicht grob falsch war. Die Erkenntnisse sind auch direkt in die C#-Software gewandert. Mit dieser kann im aktuellen Zustand die Helligkeit angezeigt werden. ="Kalibrierung" der Lichtquelle= Das Luxmeter musste ich selbstverständlich zurückgeben, aber was nun, wenn plötzlich und völlig unerwartet wieder ein Lichtsensor auf dem Tisch liegt und getestet werden muss, ob er richtig liegt, wenn das Licht angeht? Warum nicht einfach schauen, wie stabil die Lichtquelle ist? Natürlich ist der 15-Minuten-Aufbau nichts, was man für professionelle Zwecke auch nur in Erwägung ziehen würde, aber für den Heimbedarf - und um einen groben Anhaltspunkt zu finden: warum nicht? LEDs verändern sich in ihrem Leben. Wie sie bei Umgebungstemperatur altern: da habe ich kein wirkliches Gefühl. Allerdings weiß ich sehr genau, dass sie mit der Betriebszeit und durch Temperatur altern. Zugleich können sie ihre momentane Ausbeuten durch Erwärmung verändern. Da der Aufbau vermutlich nur für kurze Tests verwendet werden soll, kann die "Abnutzung" durch Betriebsdauer vernachlässigt werden. Anders ist es bei der Veränderung durch Betriebstemperatur. Allerdings kann man das relativ einfach testen: LEDs auf maximaler Leistung betrieben, Lichtsensor darunter packen und während den laufenden Messungen warten. Nach gut 20 Minuten (Länger ist das Ding wahrscheinlich eh nie am Stück im Betrieb) tat sich: nichts. Die LEDs sind offensichtlich stabil genug - oder die Messeinrichtung zu ungenau. Wer weiß. Auf jeden Fall habe ich jetzt eine zumindest grob brauchbare Ergebnisse, falls mal wieder ein Sensor vermessen werden will. =Leiterkarten= Ein paar der oben gezeigten Leiterkarte sind noch übrig. Wer will, kann eine haben. =Downloads= * [Datei:apds9300.zip] Alle Sourcen und Messdaten samt Auswertung. [[Kategorie:Elektronik]] [[Kategorie:PC]] [[Kategorie:Sensor]] f074bfa8d24101e4c9bf4b3cfd260a4b57242589 1024 1023 2016-01-02T14:32:47Z Chris 2 wikitext text/x-wiki Vor einiger Zeit (genau genommen noch im Studium) wollte ich mit Lichtsensoren (ambient light sensors, ALS) spielen. Da ich bei Farnell bestellen konnte, kamen zwei Avago APDS-9300 mit auf das Bestellformular (Mittlerweile auch beim blauen Claus bzw. Völkner zu haben). Aufgrund der Bauform und Zeitmangel blieben sie relativ lange in der ESD-Tüte. =Der Sensor= Was soll man groß Worte über einen Lichtsensor verschwenden? Licht rein, aufbereitetes Signal raus und gut ist. Ganz so einfach ist es (zumindest beim APDS-9300) leider nicht. Viele optische Sensoren drehen bei Infrarot wild, das menschliche Auge zeichnet sich dagegen als ziemlich unempfindlich aus. In Digitalkameras werden aus diesem Grund IR-Filter verbaut (die Astrofotografen wieder entfernen), allerdings scheint das den Entwicklern bei Avago entweder zu teuer oder zu unpraktisch gewesen zu sein - sie haben zwei Fotodioden verbaut: Eine ist empfindlich auf das sichtbare Licht und Infrarot, die andere nur auf Infrarot (siehe Seite 7 vom Datenblatt). Der Rest ist Mathematik. Da die menschliche Wahrnehmung weitestgehend logarithmisch ist, braucht man zur Nachbildung einen großen Dynamikumfang. Daher kann der ALS mehrere Betriebsmodi. Zum einen kann man die Integrationszeit (also die Zeit, in der die Lichtdosis gesammelt wird) wählen - konkret zwischen 13,7 ms, 101 ms und 402 ms. Zum anderen kann man einen 16-fach-Verstärker zuschalten. Dadurch gewinnt man zwar Empfindlichkeit, bezahlt die aber mit der Auflösung und Rauschen. Die Wahl der richtigen Einstellung hängt selbstverständlich von der Umgebungshelligkeit ab, ansonsten liest man entweder 0 oder der bekommt Werte in der Sättigung, die einfach keinen Sinn ergeben. =Hardware= Bei der Fertigung meiner ersten Fuhre Leiterkarten bei DirtyPCBs landete auch ein kleines Breakout-Board auf dem Panel: <gallery> Datei:apds9300_sch.png|Schaltplan, Datei:apds9300_brd.png|Layout Datei:apds9300_asy.png|und aufgebautes Sensormodul </gallery> Neben dem Sensor selbst befindet sich aufgrund dessen etwas unpraktischen Versorgungsspannung ein 2,5 V-LDO-Spannungsregler. Die Wahl auf den LDO fiel, damit die Schaltung neben den eher altmodischen 5 V auch bei 3,3 V (und somit zum Beispiel mit dem Raspberry Pi) funktioniert. Als Schnittstelle dient bei dem Lichtsensor I²C, die Treiberstufen sind hier zwar zwangsläufig Open Drain und können deshalb in aller Regel etwas höhere Spannungen als die Betriebsspannung ab, bei den Eingangstufen bzw. ESD-Schutz wird es für das Bauteil bei höheren Spannungen ungemütlicher. ==Levelshifter== Damit man den I²C mit höherer Spannung betreiben kann, wird ein (bzw. eher zwei) Levelshifter benötigt. Diesen kann man entweder fertig kaufen oder mit nur wenigen Bauteilen aufbauen - [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] erklärt, wie es funktioniert. Für alle, die zu faul zum Klicken oder des Englischen nicht ganz so mächtig sind: Bei der Schaltung wird sowohl die Body-Diode als auch die schaltende Wirkung des FET genutzt (und als Beifang die Pull-Up-Widerstände, die man für I²C eh braucht). Das Schaltungsprinzip ist einfach wie genial: Wird keine der beiden Seiten auf Masse gezogen, ist U_GS nahezu 0 oder zumindest weit unter U_GS,th - der FET sperrt und dadurch dass die Spannung auf der Kathoden-Seite der Diode höher als auf der Anoden-Seite ist, sehen sich die Schaltungsteile nicht. Den Rest erledigen die Pull-ups. Wird auf der 3,3 V-Seite das Signal auf Masse gezogen, steigt U_GS über U_GS,th und der Transistor beginnt zu leiten. Dadurch sieht man auf der 5 V-Seite die Masse der 3,3 V-Seite. Szenario Nummer 3 ist nicht ganz so offensichtlich: Wird die 5 V-Seite auf Masse gezogen, fällt zunächst der Drain-Pin des FETs auf Masse. Jetzt kommt ein Teil vom Transistor ins Spiel, der einem manchmal einen Knoten ins Gehirn macht: Die Body-Diode. Ist auf deren Kathoden-Seite ein niedrigeres Potenzial als auf deren Anoden-Seite, wird sie leitfähig, somit zieht sie den Source-Pin ebenfalls gegen die Masse, die auf der Source-Seite anliegt. Gegen - nicht auf - da noch ein bisschen Vorwärtsspannung abfällt. Allerdings fällt steigt auch U_GS über U_GS,th (der zweite Knoten im Gehirn) und der FET wird leitfähig. Somit ist die Masse der 5 V-Seite auf der 3,3 V-Seite (relativ) sauber sichtbar. Fertig ist der pillepalle einfache bidirektionale Levelshifter. Einziger Nachteil: die Spannung "links" muss immer kleiner sein als die "rechts". Zudem ist man mit den Spannungspegeln begrenzt (zum einen durch U_GS,th des FET und zum anderen durch die U_f der Body-Diode). Übrigens kann man durch das Abklemmen des Gates die Seite mit der niedrigeren Spannung isolieren. =Software - der erste Versuch= Wie kann man relativ einfach mit I²C basteln? Bei denen im PC kommt man zumindest unter Windows nicht ran (und will es [http://www.paintyourdragon.com/?p=43vermutlich auch nicht]), bei Mikrocontrollern muss man erst Soft- und Hardware basteln - das ist aufwändig und fehleranfällig. Was liegt also näher, als den Raspberry Pi zu verwenden? Dort gibt es neben den [https://github.com/groeck/i2c-tools i2c-tools] auch eine Integration in Python. Da ich keine besonderen Erfahrungen mit letztere Sprache habe, möge man mir die Codequalität entschuldigen. apds9300.py ist eine Klasse, die die Kommunikation mit dem Sensor beinhaltet. Mit viewapds.py wird der Sensor im Halbsekunden-Takt ausgelesen und sowohl die rohen als auch der berechnete Wert ausgegeben. So viel zur Theorie. In der Praxis verwandelte sich die Verwunderung sehr schnell in Verzweiflung - es kamen einfach keine auch nur halbwegs sinnvollen Werte heraus. Zuerst hatte ich meine kläglichen Versuche in Python im Verdacht, nach mehrmaligem Überprüfen und neu schreiben stellte sich allerdings heraus, dass anscheinend etwas mit dem Chip oder Datenblatt nicht passt, denn ein Vergleich mit [[wpde:Lux_(Einheit)#Beispiele_typischer_Beleuchtungsst.C3.A4rken typischen Werten|Beispielen]] in Wikipedia sagte mir nur: du liegst falsch. Nach ein paar Recherchen stellte sich heraus, dass der APDS-9300 auf einem anderen Sensor basiert (oder zumindest nicht verleugenbare Ähnlichkeiten besitzt), dem TS256x von TAOS. Auch der physische Aufbau hat gewisse Ähnlichkeiten (und die Formeln zur Berechnung der Helligkeit ebenfalls). Zudem hatten auch schon andere das Problem mit den Berechnungen, nur gab es keine Lösung. =Kalibrierung= Da hilft nur noch eines: Kalibrieren. Nur gegen was? Die Helligkeitswerte aus dem oben erwähnten Wikipedia-Artikel kann man nicht so einfach und vor allem nicht so genau nachstellen, also muss entweder eine kalibrierte Lichtquelle her oder Vergleichsmessungen gemacht werden. Es liegen ja genügend "Messgeräte" in Form von Handy und Tablet herum. Mit einer [https://play.google.com/store/apps/details?id=com.notquitethem.android.luxmeter passenden App] bekommt man die Helligkeit mundgerecht angezeigt, nur: bei meinen HTC (Sensation, Flyer und [http://hobbyelektronik.org/b/2013/02/transplantation-geglueckt-patient-muss-sterben/ Explorer]) kann man nur zwischen heller Sommertag, bedeckter Sommertag und Zappenduster unterscheiden. Das LG-Handy war in der interessanten Zeit in Reparatur und das Samsung-Tablet hatte zwar eine sehr hohe Auflösung aber dafür eine völlig unbrauchbare Winkelabhängigkeit. Ich habe mir sogar überlegt, mit der Fotokamera zu messen. Aber wie zum Henker kommt man von Blende, Belichtungszeit, Bildempfindlichkeit und Bildausschnitt auf einen brauchbaren Helligkeitswert in Lux? Nachdem die Granularität durch die festen Schritte bei den drei ersten Parametern recht schlecht ist und die Messung durch den Bildausschnitt noch heikler wird, habe ich es bei der Idee belassen. Es muss also ein geeignetes Messgerät her. Nur für das Vermessen eines Sensors Messequipment kaufen (das den Sensor auch gleich ersetzt)? Muss nicht sein: ==Minolta T-10== In der Arbeit ist u. a. ein portables Luxmeter vorhanden und ich durfte es mir freundlicherweise für zwei Wochenenden ausleihen. Das Teil hat eine RS-232-Schnittstelle, wenn auch mit einem etwas komischen Stecker. Nach der Protokollbeschreibung muss man etwas suchen, allerdings ist die Implementierung (abgesehen vom etwas verschwurbelten Ausgabeformat) relativ einfach zu bewerkstelligen. Wer in die Verlegenheit kommt, so ein T-10 (oder vergleichbare Modelle) auszulesen: unten in den Downloads gibt es sowohl für Python als auch C# Quelltexte. ==Versuch 1== Der Messaufbau umfasst: * ALS und Luxmeter (über USB-RS232-Wandler) am Pi * eine windig zusammengebaute Lichtquelle aus LED-Streifen, Kühlkörper und Diffusor aus einem alten Notebook-Display. * Ein Rigol DP832 als Spannungsquelle * Eine Metallschiene sowie ein Pappkarton zum Aufbauen eines "Lichtgalgen" Beide Lichtsensoren (Minolta und mein Kalibrierkandidat) wurden auf gleiche Ebene gebracht (wichtig!) und fixiert. Das Netzteil kann Spannungs- und Stromsweeps, die für solch einen Zweck auf den ersten Blick perfekt geeignet sind. Also den Strom von 0 bis IIRC knapp 1,5 A in 400 Schritten zu je 2 Sekunden durchlaufen lassen, das Messgerät und Sensor mit etwas höherer Frequenz abfragen und in eine Log schreiben lassen. Das Ganze mit allen möglichen Konfigurationen des ALS. Excel auf dem großen PC macht den Rest. Naja, denkste. Die Helligkeit ging alles andere als linear hoch. Die Daten habe ich direkt weggeworfen und die Messung erneut mit Variation Spannung laufen lassen - entgegen dem allgemeinen Glauben ging die Helligkeit linear hoch. Trotzdem ist und bleibt die Regel: LEDs über Stromquellen versorgen. Die Gründe breite ich hier jetzt nicht aus. Dort die beiden Helligkeitswerte im X-Y-Diagramm auftragen lassen und feststellen, dass der Sensor fernab von dem ist, was zu erwarten ist. Genauso sind die Daten in der Hinsicht etwas ungeschickt zum Auswerten, dass es für jede tatsächliche Helligkeit mehrere Wertepaare gibt. Gleichzeitig gibt es aber auch (erwartungsgemäß) ungültige Wertpaare, da ein Sensor vor und der andere nach dem Umschalten der Spannung ausgelesen wurde. Die ganzen Messartefakte kann man zwar filtern, aber das ist unnötig und nervig. Nachdem die ganzen Messungen durch waren, musste das Luxmeter auch schon wieder zurück in die Arbeit. Nachdem der erste Lauf vielversprechend war, glaube ich, dass die anderen Messungen ok waren. Zudem war es viel zu heiß (Sommer 2015), um im Büro zu sitzen. Long story short: ein kleiner Programmierfehler und die Integrationszeiten wurden nicht in den Sensor geschrieben. <gallery> Datei:apds9300_diag_1_1.png|Verstärkung = 1; Integrationszeit = 13,7ms Datei:apds9300_diag_1_2.png|Verstärkung = 16; Integrationszeit = 13,7ms </gallery> Aarrgghh! ==Versuch 2== Fehler darf man machen, solange man daraus lernt. Das Rigol kann USB, und für das Auslesen des ALS habe ich eine Schaltung mit dem [http://hobbyelektronik.org/b/2015/09/mcp2221/ MCP2221] aufgebaut. Die Lichtquelle bleibt die selbe, sie steckt aber nun in der Decke eines Schuhkartons. Dadurch kann der Abstand, Position und Helligkeit (Streulicht!) relativ gut definiert werden: <gallery> Datei:apds9300_box.png|Aufbau der Messbox </gallery> Software: Dieses Mal in C#. Das kenne ich halbwegs und mag es. ===Automatisierung=== Zur Ansteuerung vom Netzteil muss erst einmal [https://www.ni.com/visa/ NI VISA] installiert werden. Ich hasse es, ich liebe es. Ich hasse es, weil die VISA-Treiber ein riesiges Bollwerk sind und man beim ersten Versuch immer die falschen erwischt. Zudem gibt es einen schönen Bug, bei dem Windows nach deren Installation irgendwann anfängt, knapp 20 Minuten für den Login zu braucht. Den [http://digital.ni.com/public.nsf/allkb/814FEF952915137686257B6B006C5F4F?OpenDocument offiziellen Fix] habe ich selbst noch nicht getestet, mit der im [http://forums.ni.com/t5/LabVIEW/Issues-with-windows-7-after-Labview-2012-installation/m-p/2257858#M715816 NI-Forum] beschriebenen Vorgehensweise habe ich gute Erfahrungen gemacht. Dadurch macht man sich unter Umständen zwar [[wpde:LAN eXtensions for Instrumentation|LXI]] kaputt, was in den meisten Fällen eh nicht verwendet wird. Was ich an VISA liebe? [[wpde:SCPI|SCPI]]! Messautomatisierung ist etwas wirklich feines und nicht nur, weil man auf dem Weg in die Mittagspause noch kurz "MAHLZEIT" auf dem Multimeter anzeigen lassen kann. Mir hat es in der Arbeit bereits unbeschreiblich viel manuelle Messzeit erspart. Dazu kommt, dass die Wiederholbarkeit sehr gut ist. Wie auch immer, die Software ist schnell und hässlich - aber zweckmäßig - runtergerissen. Die Messungen sind zum Einstellen der Helligkeit der Lichtquelle synchronisiert und neben den deutlich besseren Ergebnissen kann ich zugleich meine Lichtquelle kalibrieren. Ein Messlauf dauert nicht ganz zwei Minuten, wegen der unterschiedlichen Integrationszeiten und den beiden möglichen Verstärkungsfaktoren mal 6 und schon hat man einen Sensor vermessen. ==Auswertung== Das ganze nochmal in Excel verwurstet und es sieht gar nicht mal so gut aus: <gallery> Datei:apds9300_diag_2_1.png|Messergebnisse 1. Sensor mit Gain = 1 Datei:apds9300_diag_2_2.png|Messergebnisse 1. Sensor mit Gain = 16 </gallery> Im ersten Diagramm sieht man, dass die Werte schön und nahezu linear nach oben gehen, allerdings ist da - je nach Integrationslänge ordentlich Faktor drauf. Bei der Ausgabe wurde die Integrationszeit nicht berücksichtigt. Die Einbrüche im zweiten Diagramm lassen sich durch die tatsächlichen Messwerte erklären: <gallery> Datei:apds9300_diag_2_1.png|Messwerte ohne und 16-facher Verstärkung </gallery> Kanal 0 geht bei 16-facher Verstärkung sehr früh in Sättigung - das ist alles. Ok, nun müssen die Helligkeitswerte noch richtig skaliert werden. Meine Vermutung geht stark in die Richtung, dass entweder die Lichtempfindlichkeit oder die Integrationszeit bei den Sensoren nicht ganz richtig sind. Man kann den Korrekturfaktor zwar auf die berechnete Helligkeit anwenden - dadurch dass es in den Berechnungen keine Offsets gibt, sollte das auch funktionieren. Mir ist es allerdings deutlich lieber, direkt die rohen Werte zu behandeln. Also die Messwerte skalieren, durch die Formel zur Berechnung der Helligkeit jagen und das Ergebnis vergleichen. Excel kann das relativ gut automatisch - mit der Zielwertsuche. Der Parameter dafür ist die prozentuale Abweichung der berechneten Helligkeit und der Referenzmessung vom Luxmeter. Damit das Ganze funktioniert, muss der Algorithmus zur Berechnung in Excel implementiert werden. Ich habe aufgehört zu zählen... Unter Berücksichtigung der Integrationszeiten ergibt sich ein Faktor von relativ genau 0,2, um auf die "richtige" Helligkeit zu kommen. Zum Vermessen des zweiten Sensors habe ich diesen Faktor für die Berechnung des ausgegebenen Wertes in meine Software eingetragen und es kommt relativ gut hin - über den kompletten Messbereich war die Abweichung nicht größer als 5 %. Selbstverständlich ist das statistisch nicht aussagekräftig aber trotzdem eine Bestätigung, dass die ganze Aktion nicht grob falsch war. Die Erkenntnisse sind auch direkt in die C#-Software gewandert. Mit dieser kann im aktuellen Zustand die Helligkeit angezeigt werden. ="Kalibrierung" der Lichtquelle= Das Luxmeter musste ich selbstverständlich zurückgeben, aber was nun, wenn plötzlich und völlig unerwartet wieder ein Lichtsensor auf dem Tisch liegt und getestet werden muss, ob er richtig liegt, wenn das Licht angeht? Warum nicht einfach schauen, wie stabil die Lichtquelle ist? Natürlich ist der 15-Minuten-Aufbau nichts, was man für professionelle Zwecke auch nur in Erwägung ziehen würde, aber für den Heimbedarf - und um einen groben Anhaltspunkt zu finden: warum nicht? LEDs verändern sich in ihrem Leben. Wie sie bei Umgebungstemperatur altern: da habe ich kein wirkliches Gefühl. Allerdings weiß ich sehr genau, dass sie mit der Betriebszeit und durch Temperatur altern. Zugleich können sie ihre momentane Ausbeuten durch Erwärmung verändern. Da der Aufbau vermutlich nur für kurze Tests verwendet werden soll, kann die "Abnutzung" durch Betriebsdauer vernachlässigt werden. Anders ist es bei der Veränderung durch Betriebstemperatur. Allerdings kann man das relativ einfach testen: LEDs auf maximaler Leistung betrieben, Lichtsensor darunter packen und während den laufenden Messungen warten. Nach gut 20 Minuten (Länger ist das Ding wahrscheinlich eh nie am Stück im Betrieb) tat sich: nichts. Die LEDs sind offensichtlich stabil genug - oder die Messeinrichtung zu ungenau. Wer weiß. Auf jeden Fall habe ich jetzt eine zumindest grob brauchbare Ergebnisse, falls mal wieder ein Sensor vermessen werden will. =Leiterkarten= Ein paar der oben gezeigten Leiterkarte sind noch übrig. Wer will, kann eine haben. =Downloads= * [[Datei:apds9300.zip]] Alle Sourcen und Messdaten samt Auswertung. [[Kategorie:Elektronik]] [[Kategorie:PC]] [[Kategorie:Sensor]] ecb2f88441066d7cfaa62f3ec42661f37d9d16d0 1025 1024 2016-01-02T14:36:30Z Chris 2 verschob „[[APDS-9300]]“ nach „[[Lichtsensor Avago APDS-9300]]“: besserer Seitentitel wikitext text/x-wiki Vor einiger Zeit (genau genommen noch im Studium) wollte ich mit Lichtsensoren (ambient light sensors, ALS) spielen. Da ich bei Farnell bestellen konnte, kamen zwei Avago APDS-9300 mit auf das Bestellformular (Mittlerweile auch beim blauen Claus bzw. Völkner zu haben). Aufgrund der Bauform und Zeitmangel blieben sie relativ lange in der ESD-Tüte. =Der Sensor= Was soll man groß Worte über einen Lichtsensor verschwenden? Licht rein, aufbereitetes Signal raus und gut ist. Ganz so einfach ist es (zumindest beim APDS-9300) leider nicht. Viele optische Sensoren drehen bei Infrarot wild, das menschliche Auge zeichnet sich dagegen als ziemlich unempfindlich aus. In Digitalkameras werden aus diesem Grund IR-Filter verbaut (die Astrofotografen wieder entfernen), allerdings scheint das den Entwicklern bei Avago entweder zu teuer oder zu unpraktisch gewesen zu sein - sie haben zwei Fotodioden verbaut: Eine ist empfindlich auf das sichtbare Licht und Infrarot, die andere nur auf Infrarot (siehe Seite 7 vom Datenblatt). Der Rest ist Mathematik. Da die menschliche Wahrnehmung weitestgehend logarithmisch ist, braucht man zur Nachbildung einen großen Dynamikumfang. Daher kann der ALS mehrere Betriebsmodi. Zum einen kann man die Integrationszeit (also die Zeit, in der die Lichtdosis gesammelt wird) wählen - konkret zwischen 13,7 ms, 101 ms und 402 ms. Zum anderen kann man einen 16-fach-Verstärker zuschalten. Dadurch gewinnt man zwar Empfindlichkeit, bezahlt die aber mit der Auflösung und Rauschen. Die Wahl der richtigen Einstellung hängt selbstverständlich von der Umgebungshelligkeit ab, ansonsten liest man entweder 0 oder der bekommt Werte in der Sättigung, die einfach keinen Sinn ergeben. =Hardware= Bei der Fertigung meiner ersten Fuhre Leiterkarten bei DirtyPCBs landete auch ein kleines Breakout-Board auf dem Panel: <gallery> Datei:apds9300_sch.png|Schaltplan, Datei:apds9300_brd.png|Layout Datei:apds9300_asy.png|und aufgebautes Sensormodul </gallery> Neben dem Sensor selbst befindet sich aufgrund dessen etwas unpraktischen Versorgungsspannung ein 2,5 V-LDO-Spannungsregler. Die Wahl auf den LDO fiel, damit die Schaltung neben den eher altmodischen 5 V auch bei 3,3 V (und somit zum Beispiel mit dem Raspberry Pi) funktioniert. Als Schnittstelle dient bei dem Lichtsensor I²C, die Treiberstufen sind hier zwar zwangsläufig Open Drain und können deshalb in aller Regel etwas höhere Spannungen als die Betriebsspannung ab, bei den Eingangstufen bzw. ESD-Schutz wird es für das Bauteil bei höheren Spannungen ungemütlicher. ==Levelshifter== Damit man den I²C mit höherer Spannung betreiben kann, wird ein (bzw. eher zwei) Levelshifter benötigt. Diesen kann man entweder fertig kaufen oder mit nur wenigen Bauteilen aufbauen - [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] erklärt, wie es funktioniert. Für alle, die zu faul zum Klicken oder des Englischen nicht ganz so mächtig sind: Bei der Schaltung wird sowohl die Body-Diode als auch die schaltende Wirkung des FET genutzt (und als Beifang die Pull-Up-Widerstände, die man für I²C eh braucht). Das Schaltungsprinzip ist einfach wie genial: Wird keine der beiden Seiten auf Masse gezogen, ist U_GS nahezu 0 oder zumindest weit unter U_GS,th - der FET sperrt und dadurch dass die Spannung auf der Kathoden-Seite der Diode höher als auf der Anoden-Seite ist, sehen sich die Schaltungsteile nicht. Den Rest erledigen die Pull-ups. Wird auf der 3,3 V-Seite das Signal auf Masse gezogen, steigt U_GS über U_GS,th und der Transistor beginnt zu leiten. Dadurch sieht man auf der 5 V-Seite die Masse der 3,3 V-Seite. Szenario Nummer 3 ist nicht ganz so offensichtlich: Wird die 5 V-Seite auf Masse gezogen, fällt zunächst der Drain-Pin des FETs auf Masse. Jetzt kommt ein Teil vom Transistor ins Spiel, der einem manchmal einen Knoten ins Gehirn macht: Die Body-Diode. Ist auf deren Kathoden-Seite ein niedrigeres Potenzial als auf deren Anoden-Seite, wird sie leitfähig, somit zieht sie den Source-Pin ebenfalls gegen die Masse, die auf der Source-Seite anliegt. Gegen - nicht auf - da noch ein bisschen Vorwärtsspannung abfällt. Allerdings fällt steigt auch U_GS über U_GS,th (der zweite Knoten im Gehirn) und der FET wird leitfähig. Somit ist die Masse der 5 V-Seite auf der 3,3 V-Seite (relativ) sauber sichtbar. Fertig ist der pillepalle einfache bidirektionale Levelshifter. Einziger Nachteil: die Spannung "links" muss immer kleiner sein als die "rechts". Zudem ist man mit den Spannungspegeln begrenzt (zum einen durch U_GS,th des FET und zum anderen durch die U_f der Body-Diode). Übrigens kann man durch das Abklemmen des Gates die Seite mit der niedrigeren Spannung isolieren. =Software - der erste Versuch= Wie kann man relativ einfach mit I²C basteln? Bei denen im PC kommt man zumindest unter Windows nicht ran (und will es [http://www.paintyourdragon.com/?p=43vermutlich auch nicht]), bei Mikrocontrollern muss man erst Soft- und Hardware basteln - das ist aufwändig und fehleranfällig. Was liegt also näher, als den Raspberry Pi zu verwenden? Dort gibt es neben den [https://github.com/groeck/i2c-tools i2c-tools] auch eine Integration in Python. Da ich keine besonderen Erfahrungen mit letztere Sprache habe, möge man mir die Codequalität entschuldigen. apds9300.py ist eine Klasse, die die Kommunikation mit dem Sensor beinhaltet. Mit viewapds.py wird der Sensor im Halbsekunden-Takt ausgelesen und sowohl die rohen als auch der berechnete Wert ausgegeben. So viel zur Theorie. In der Praxis verwandelte sich die Verwunderung sehr schnell in Verzweiflung - es kamen einfach keine auch nur halbwegs sinnvollen Werte heraus. Zuerst hatte ich meine kläglichen Versuche in Python im Verdacht, nach mehrmaligem Überprüfen und neu schreiben stellte sich allerdings heraus, dass anscheinend etwas mit dem Chip oder Datenblatt nicht passt, denn ein Vergleich mit [[wpde:Lux_(Einheit)#Beispiele_typischer_Beleuchtungsst.C3.A4rken typischen Werten|Beispielen]] in Wikipedia sagte mir nur: du liegst falsch. Nach ein paar Recherchen stellte sich heraus, dass der APDS-9300 auf einem anderen Sensor basiert (oder zumindest nicht verleugenbare Ähnlichkeiten besitzt), dem TS256x von TAOS. Auch der physische Aufbau hat gewisse Ähnlichkeiten (und die Formeln zur Berechnung der Helligkeit ebenfalls). Zudem hatten auch schon andere das Problem mit den Berechnungen, nur gab es keine Lösung. =Kalibrierung= Da hilft nur noch eines: Kalibrieren. Nur gegen was? Die Helligkeitswerte aus dem oben erwähnten Wikipedia-Artikel kann man nicht so einfach und vor allem nicht so genau nachstellen, also muss entweder eine kalibrierte Lichtquelle her oder Vergleichsmessungen gemacht werden. Es liegen ja genügend "Messgeräte" in Form von Handy und Tablet herum. Mit einer [https://play.google.com/store/apps/details?id=com.notquitethem.android.luxmeter passenden App] bekommt man die Helligkeit mundgerecht angezeigt, nur: bei meinen HTC (Sensation, Flyer und [http://hobbyelektronik.org/b/2013/02/transplantation-geglueckt-patient-muss-sterben/ Explorer]) kann man nur zwischen heller Sommertag, bedeckter Sommertag und Zappenduster unterscheiden. Das LG-Handy war in der interessanten Zeit in Reparatur und das Samsung-Tablet hatte zwar eine sehr hohe Auflösung aber dafür eine völlig unbrauchbare Winkelabhängigkeit. Ich habe mir sogar überlegt, mit der Fotokamera zu messen. Aber wie zum Henker kommt man von Blende, Belichtungszeit, Bildempfindlichkeit und Bildausschnitt auf einen brauchbaren Helligkeitswert in Lux? Nachdem die Granularität durch die festen Schritte bei den drei ersten Parametern recht schlecht ist und die Messung durch den Bildausschnitt noch heikler wird, habe ich es bei der Idee belassen. Es muss also ein geeignetes Messgerät her. Nur für das Vermessen eines Sensors Messequipment kaufen (das den Sensor auch gleich ersetzt)? Muss nicht sein: ==Minolta T-10== In der Arbeit ist u. a. ein portables Luxmeter vorhanden und ich durfte es mir freundlicherweise für zwei Wochenenden ausleihen. Das Teil hat eine RS-232-Schnittstelle, wenn auch mit einem etwas komischen Stecker. Nach der Protokollbeschreibung muss man etwas suchen, allerdings ist die Implementierung (abgesehen vom etwas verschwurbelten Ausgabeformat) relativ einfach zu bewerkstelligen. Wer in die Verlegenheit kommt, so ein T-10 (oder vergleichbare Modelle) auszulesen: unten in den Downloads gibt es sowohl für Python als auch C# Quelltexte. ==Versuch 1== Der Messaufbau umfasst: * ALS und Luxmeter (über USB-RS232-Wandler) am Pi * eine windig zusammengebaute Lichtquelle aus LED-Streifen, Kühlkörper und Diffusor aus einem alten Notebook-Display. * Ein Rigol DP832 als Spannungsquelle * Eine Metallschiene sowie ein Pappkarton zum Aufbauen eines "Lichtgalgen" Beide Lichtsensoren (Minolta und mein Kalibrierkandidat) wurden auf gleiche Ebene gebracht (wichtig!) und fixiert. Das Netzteil kann Spannungs- und Stromsweeps, die für solch einen Zweck auf den ersten Blick perfekt geeignet sind. Also den Strom von 0 bis IIRC knapp 1,5 A in 400 Schritten zu je 2 Sekunden durchlaufen lassen, das Messgerät und Sensor mit etwas höherer Frequenz abfragen und in eine Log schreiben lassen. Das Ganze mit allen möglichen Konfigurationen des ALS. Excel auf dem großen PC macht den Rest. Naja, denkste. Die Helligkeit ging alles andere als linear hoch. Die Daten habe ich direkt weggeworfen und die Messung erneut mit Variation Spannung laufen lassen - entgegen dem allgemeinen Glauben ging die Helligkeit linear hoch. Trotzdem ist und bleibt die Regel: LEDs über Stromquellen versorgen. Die Gründe breite ich hier jetzt nicht aus. Dort die beiden Helligkeitswerte im X-Y-Diagramm auftragen lassen und feststellen, dass der Sensor fernab von dem ist, was zu erwarten ist. Genauso sind die Daten in der Hinsicht etwas ungeschickt zum Auswerten, dass es für jede tatsächliche Helligkeit mehrere Wertepaare gibt. Gleichzeitig gibt es aber auch (erwartungsgemäß) ungültige Wertpaare, da ein Sensor vor und der andere nach dem Umschalten der Spannung ausgelesen wurde. Die ganzen Messartefakte kann man zwar filtern, aber das ist unnötig und nervig. Nachdem die ganzen Messungen durch waren, musste das Luxmeter auch schon wieder zurück in die Arbeit. Nachdem der erste Lauf vielversprechend war, glaube ich, dass die anderen Messungen ok waren. Zudem war es viel zu heiß (Sommer 2015), um im Büro zu sitzen. Long story short: ein kleiner Programmierfehler und die Integrationszeiten wurden nicht in den Sensor geschrieben. <gallery> Datei:apds9300_diag_1_1.png|Verstärkung = 1; Integrationszeit = 13,7ms Datei:apds9300_diag_1_2.png|Verstärkung = 16; Integrationszeit = 13,7ms </gallery> Aarrgghh! ==Versuch 2== Fehler darf man machen, solange man daraus lernt. Das Rigol kann USB, und für das Auslesen des ALS habe ich eine Schaltung mit dem [http://hobbyelektronik.org/b/2015/09/mcp2221/ MCP2221] aufgebaut. Die Lichtquelle bleibt die selbe, sie steckt aber nun in der Decke eines Schuhkartons. Dadurch kann der Abstand, Position und Helligkeit (Streulicht!) relativ gut definiert werden: <gallery> Datei:apds9300_box.png|Aufbau der Messbox </gallery> Software: Dieses Mal in C#. Das kenne ich halbwegs und mag es. ===Automatisierung=== Zur Ansteuerung vom Netzteil muss erst einmal [https://www.ni.com/visa/ NI VISA] installiert werden. Ich hasse es, ich liebe es. Ich hasse es, weil die VISA-Treiber ein riesiges Bollwerk sind und man beim ersten Versuch immer die falschen erwischt. Zudem gibt es einen schönen Bug, bei dem Windows nach deren Installation irgendwann anfängt, knapp 20 Minuten für den Login zu braucht. Den [http://digital.ni.com/public.nsf/allkb/814FEF952915137686257B6B006C5F4F?OpenDocument offiziellen Fix] habe ich selbst noch nicht getestet, mit der im [http://forums.ni.com/t5/LabVIEW/Issues-with-windows-7-after-Labview-2012-installation/m-p/2257858#M715816 NI-Forum] beschriebenen Vorgehensweise habe ich gute Erfahrungen gemacht. Dadurch macht man sich unter Umständen zwar [[wpde:LAN eXtensions for Instrumentation|LXI]] kaputt, was in den meisten Fällen eh nicht verwendet wird. Was ich an VISA liebe? [[wpde:SCPI|SCPI]]! Messautomatisierung ist etwas wirklich feines und nicht nur, weil man auf dem Weg in die Mittagspause noch kurz "MAHLZEIT" auf dem Multimeter anzeigen lassen kann. Mir hat es in der Arbeit bereits unbeschreiblich viel manuelle Messzeit erspart. Dazu kommt, dass die Wiederholbarkeit sehr gut ist. Wie auch immer, die Software ist schnell und hässlich - aber zweckmäßig - runtergerissen. Die Messungen sind zum Einstellen der Helligkeit der Lichtquelle synchronisiert und neben den deutlich besseren Ergebnissen kann ich zugleich meine Lichtquelle kalibrieren. Ein Messlauf dauert nicht ganz zwei Minuten, wegen der unterschiedlichen Integrationszeiten und den beiden möglichen Verstärkungsfaktoren mal 6 und schon hat man einen Sensor vermessen. ==Auswertung== Das ganze nochmal in Excel verwurstet und es sieht gar nicht mal so gut aus: <gallery> Datei:apds9300_diag_2_1.png|Messergebnisse 1. Sensor mit Gain = 1 Datei:apds9300_diag_2_2.png|Messergebnisse 1. Sensor mit Gain = 16 </gallery> Im ersten Diagramm sieht man, dass die Werte schön und nahezu linear nach oben gehen, allerdings ist da - je nach Integrationslänge ordentlich Faktor drauf. Bei der Ausgabe wurde die Integrationszeit nicht berücksichtigt. Die Einbrüche im zweiten Diagramm lassen sich durch die tatsächlichen Messwerte erklären: <gallery> Datei:apds9300_diag_2_1.png|Messwerte ohne und 16-facher Verstärkung </gallery> Kanal 0 geht bei 16-facher Verstärkung sehr früh in Sättigung - das ist alles. Ok, nun müssen die Helligkeitswerte noch richtig skaliert werden. Meine Vermutung geht stark in die Richtung, dass entweder die Lichtempfindlichkeit oder die Integrationszeit bei den Sensoren nicht ganz richtig sind. Man kann den Korrekturfaktor zwar auf die berechnete Helligkeit anwenden - dadurch dass es in den Berechnungen keine Offsets gibt, sollte das auch funktionieren. Mir ist es allerdings deutlich lieber, direkt die rohen Werte zu behandeln. Also die Messwerte skalieren, durch die Formel zur Berechnung der Helligkeit jagen und das Ergebnis vergleichen. Excel kann das relativ gut automatisch - mit der Zielwertsuche. Der Parameter dafür ist die prozentuale Abweichung der berechneten Helligkeit und der Referenzmessung vom Luxmeter. Damit das Ganze funktioniert, muss der Algorithmus zur Berechnung in Excel implementiert werden. Ich habe aufgehört zu zählen... Unter Berücksichtigung der Integrationszeiten ergibt sich ein Faktor von relativ genau 0,2, um auf die "richtige" Helligkeit zu kommen. Zum Vermessen des zweiten Sensors habe ich diesen Faktor für die Berechnung des ausgegebenen Wertes in meine Software eingetragen und es kommt relativ gut hin - über den kompletten Messbereich war die Abweichung nicht größer als 5 %. Selbstverständlich ist das statistisch nicht aussagekräftig aber trotzdem eine Bestätigung, dass die ganze Aktion nicht grob falsch war. Die Erkenntnisse sind auch direkt in die C#-Software gewandert. Mit dieser kann im aktuellen Zustand die Helligkeit angezeigt werden. ="Kalibrierung" der Lichtquelle= Das Luxmeter musste ich selbstverständlich zurückgeben, aber was nun, wenn plötzlich und völlig unerwartet wieder ein Lichtsensor auf dem Tisch liegt und getestet werden muss, ob er richtig liegt, wenn das Licht angeht? Warum nicht einfach schauen, wie stabil die Lichtquelle ist? Natürlich ist der 15-Minuten-Aufbau nichts, was man für professionelle Zwecke auch nur in Erwägung ziehen würde, aber für den Heimbedarf - und um einen groben Anhaltspunkt zu finden: warum nicht? LEDs verändern sich in ihrem Leben. Wie sie bei Umgebungstemperatur altern: da habe ich kein wirkliches Gefühl. Allerdings weiß ich sehr genau, dass sie mit der Betriebszeit und durch Temperatur altern. Zugleich können sie ihre momentane Ausbeuten durch Erwärmung verändern. Da der Aufbau vermutlich nur für kurze Tests verwendet werden soll, kann die "Abnutzung" durch Betriebsdauer vernachlässigt werden. Anders ist es bei der Veränderung durch Betriebstemperatur. Allerdings kann man das relativ einfach testen: LEDs auf maximaler Leistung betrieben, Lichtsensor darunter packen und während den laufenden Messungen warten. Nach gut 20 Minuten (Länger ist das Ding wahrscheinlich eh nie am Stück im Betrieb) tat sich: nichts. Die LEDs sind offensichtlich stabil genug - oder die Messeinrichtung zu ungenau. Wer weiß. Auf jeden Fall habe ich jetzt eine zumindest grob brauchbare Ergebnisse, falls mal wieder ein Sensor vermessen werden will. =Leiterkarten= Ein paar der oben gezeigten Leiterkarte sind noch übrig. Wer will, kann eine haben. =Downloads= * [[Datei:apds9300.zip]] Alle Sourcen und Messdaten samt Auswertung. [[Kategorie:Elektronik]] [[Kategorie:PC]] [[Kategorie:Sensor]] ecb2f88441066d7cfaa62f3ec42661f37d9d16d0 1027 1025 2016-01-02T14:37:12Z Chris 2 falscher Dateilink wikitext text/x-wiki Vor einiger Zeit (genau genommen noch im Studium) wollte ich mit Lichtsensoren (ambient light sensors, ALS) spielen. Da ich bei Farnell bestellen konnte, kamen zwei Avago APDS-9300 mit auf das Bestellformular (Mittlerweile auch beim blauen Claus bzw. Völkner zu haben). Aufgrund der Bauform und Zeitmangel blieben sie relativ lange in der ESD-Tüte. =Der Sensor= Was soll man groß Worte über einen Lichtsensor verschwenden? Licht rein, aufbereitetes Signal raus und gut ist. Ganz so einfach ist es (zumindest beim APDS-9300) leider nicht. Viele optische Sensoren drehen bei Infrarot wild, das menschliche Auge zeichnet sich dagegen als ziemlich unempfindlich aus. In Digitalkameras werden aus diesem Grund IR-Filter verbaut (die Astrofotografen wieder entfernen), allerdings scheint das den Entwicklern bei Avago entweder zu teuer oder zu unpraktisch gewesen zu sein - sie haben zwei Fotodioden verbaut: Eine ist empfindlich auf das sichtbare Licht und Infrarot, die andere nur auf Infrarot (siehe Seite 7 vom Datenblatt). Der Rest ist Mathematik. Da die menschliche Wahrnehmung weitestgehend logarithmisch ist, braucht man zur Nachbildung einen großen Dynamikumfang. Daher kann der ALS mehrere Betriebsmodi. Zum einen kann man die Integrationszeit (also die Zeit, in der die Lichtdosis gesammelt wird) wählen - konkret zwischen 13,7 ms, 101 ms und 402 ms. Zum anderen kann man einen 16-fach-Verstärker zuschalten. Dadurch gewinnt man zwar Empfindlichkeit, bezahlt die aber mit der Auflösung und Rauschen. Die Wahl der richtigen Einstellung hängt selbstverständlich von der Umgebungshelligkeit ab, ansonsten liest man entweder 0 oder der bekommt Werte in der Sättigung, die einfach keinen Sinn ergeben. =Hardware= Bei der Fertigung meiner ersten Fuhre Leiterkarten bei DirtyPCBs landete auch ein kleines Breakout-Board auf dem Panel: <gallery> Datei:apds9300_sch.png|Schaltplan, Datei:apds9300_brd.png|Layout Datei:apds9300_asy.png|und aufgebautes Sensormodul </gallery> Neben dem Sensor selbst befindet sich aufgrund dessen etwas unpraktischen Versorgungsspannung ein 2,5 V-LDO-Spannungsregler. Die Wahl auf den LDO fiel, damit die Schaltung neben den eher altmodischen 5 V auch bei 3,3 V (und somit zum Beispiel mit dem Raspberry Pi) funktioniert. Als Schnittstelle dient bei dem Lichtsensor I²C, die Treiberstufen sind hier zwar zwangsläufig Open Drain und können deshalb in aller Regel etwas höhere Spannungen als die Betriebsspannung ab, bei den Eingangstufen bzw. ESD-Schutz wird es für das Bauteil bei höheren Spannungen ungemütlicher. ==Levelshifter== Damit man den I²C mit höherer Spannung betreiben kann, wird ein (bzw. eher zwei) Levelshifter benötigt. Diesen kann man entweder fertig kaufen oder mit nur wenigen Bauteilen aufbauen - [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] erklärt, wie es funktioniert. Für alle, die zu faul zum Klicken oder des Englischen nicht ganz so mächtig sind: Bei der Schaltung wird sowohl die Body-Diode als auch die schaltende Wirkung des FET genutzt (und als Beifang die Pull-Up-Widerstände, die man für I²C eh braucht). Das Schaltungsprinzip ist einfach wie genial: Wird keine der beiden Seiten auf Masse gezogen, ist U_GS nahezu 0 oder zumindest weit unter U_GS,th - der FET sperrt und dadurch dass die Spannung auf der Kathoden-Seite der Diode höher als auf der Anoden-Seite ist, sehen sich die Schaltungsteile nicht. Den Rest erledigen die Pull-ups. Wird auf der 3,3 V-Seite das Signal auf Masse gezogen, steigt U_GS über U_GS,th und der Transistor beginnt zu leiten. Dadurch sieht man auf der 5 V-Seite die Masse der 3,3 V-Seite. Szenario Nummer 3 ist nicht ganz so offensichtlich: Wird die 5 V-Seite auf Masse gezogen, fällt zunächst der Drain-Pin des FETs auf Masse. Jetzt kommt ein Teil vom Transistor ins Spiel, der einem manchmal einen Knoten ins Gehirn macht: Die Body-Diode. Ist auf deren Kathoden-Seite ein niedrigeres Potenzial als auf deren Anoden-Seite, wird sie leitfähig, somit zieht sie den Source-Pin ebenfalls gegen die Masse, die auf der Source-Seite anliegt. Gegen - nicht auf - da noch ein bisschen Vorwärtsspannung abfällt. Allerdings fällt steigt auch U_GS über U_GS,th (der zweite Knoten im Gehirn) und der FET wird leitfähig. Somit ist die Masse der 5 V-Seite auf der 3,3 V-Seite (relativ) sauber sichtbar. Fertig ist der pillepalle einfache bidirektionale Levelshifter. Einziger Nachteil: die Spannung "links" muss immer kleiner sein als die "rechts". Zudem ist man mit den Spannungspegeln begrenzt (zum einen durch U_GS,th des FET und zum anderen durch die U_f der Body-Diode). Übrigens kann man durch das Abklemmen des Gates die Seite mit der niedrigeren Spannung isolieren. =Software - der erste Versuch= Wie kann man relativ einfach mit I²C basteln? Bei denen im PC kommt man zumindest unter Windows nicht ran (und will es [http://www.paintyourdragon.com/?p=43vermutlich auch nicht]), bei Mikrocontrollern muss man erst Soft- und Hardware basteln - das ist aufwändig und fehleranfällig. Was liegt also näher, als den Raspberry Pi zu verwenden? Dort gibt es neben den [https://github.com/groeck/i2c-tools i2c-tools] auch eine Integration in Python. Da ich keine besonderen Erfahrungen mit letztere Sprache habe, möge man mir die Codequalität entschuldigen. apds9300.py ist eine Klasse, die die Kommunikation mit dem Sensor beinhaltet. Mit viewapds.py wird der Sensor im Halbsekunden-Takt ausgelesen und sowohl die rohen als auch der berechnete Wert ausgegeben. So viel zur Theorie. In der Praxis verwandelte sich die Verwunderung sehr schnell in Verzweiflung - es kamen einfach keine auch nur halbwegs sinnvollen Werte heraus. Zuerst hatte ich meine kläglichen Versuche in Python im Verdacht, nach mehrmaligem Überprüfen und neu schreiben stellte sich allerdings heraus, dass anscheinend etwas mit dem Chip oder Datenblatt nicht passt, denn ein Vergleich mit [[wpde:Lux_(Einheit)#Beispiele_typischer_Beleuchtungsst.C3.A4rken typischen Werten|Beispielen]] in Wikipedia sagte mir nur: du liegst falsch. Nach ein paar Recherchen stellte sich heraus, dass der APDS-9300 auf einem anderen Sensor basiert (oder zumindest nicht verleugenbare Ähnlichkeiten besitzt), dem TS256x von TAOS. Auch der physische Aufbau hat gewisse Ähnlichkeiten (und die Formeln zur Berechnung der Helligkeit ebenfalls). Zudem hatten auch schon andere das Problem mit den Berechnungen, nur gab es keine Lösung. =Kalibrierung= Da hilft nur noch eines: Kalibrieren. Nur gegen was? Die Helligkeitswerte aus dem oben erwähnten Wikipedia-Artikel kann man nicht so einfach und vor allem nicht so genau nachstellen, also muss entweder eine kalibrierte Lichtquelle her oder Vergleichsmessungen gemacht werden. Es liegen ja genügend "Messgeräte" in Form von Handy und Tablet herum. Mit einer [https://play.google.com/store/apps/details?id=com.notquitethem.android.luxmeter passenden App] bekommt man die Helligkeit mundgerecht angezeigt, nur: bei meinen HTC (Sensation, Flyer und [http://hobbyelektronik.org/b/2013/02/transplantation-geglueckt-patient-muss-sterben/ Explorer]) kann man nur zwischen heller Sommertag, bedeckter Sommertag und Zappenduster unterscheiden. Das LG-Handy war in der interessanten Zeit in Reparatur und das Samsung-Tablet hatte zwar eine sehr hohe Auflösung aber dafür eine völlig unbrauchbare Winkelabhängigkeit. Ich habe mir sogar überlegt, mit der Fotokamera zu messen. Aber wie zum Henker kommt man von Blende, Belichtungszeit, Bildempfindlichkeit und Bildausschnitt auf einen brauchbaren Helligkeitswert in Lux? Nachdem die Granularität durch die festen Schritte bei den drei ersten Parametern recht schlecht ist und die Messung durch den Bildausschnitt noch heikler wird, habe ich es bei der Idee belassen. Es muss also ein geeignetes Messgerät her. Nur für das Vermessen eines Sensors Messequipment kaufen (das den Sensor auch gleich ersetzt)? Muss nicht sein: ==Minolta T-10== In der Arbeit ist u. a. ein portables Luxmeter vorhanden und ich durfte es mir freundlicherweise für zwei Wochenenden ausleihen. Das Teil hat eine RS-232-Schnittstelle, wenn auch mit einem etwas komischen Stecker. Nach der Protokollbeschreibung muss man etwas suchen, allerdings ist die Implementierung (abgesehen vom etwas verschwurbelten Ausgabeformat) relativ einfach zu bewerkstelligen. Wer in die Verlegenheit kommt, so ein T-10 (oder vergleichbare Modelle) auszulesen: unten in den Downloads gibt es sowohl für Python als auch C# Quelltexte. ==Versuch 1== Der Messaufbau umfasst: * ALS und Luxmeter (über USB-RS232-Wandler) am Pi * eine windig zusammengebaute Lichtquelle aus LED-Streifen, Kühlkörper und Diffusor aus einem alten Notebook-Display. * Ein Rigol DP832 als Spannungsquelle * Eine Metallschiene sowie ein Pappkarton zum Aufbauen eines "Lichtgalgen" Beide Lichtsensoren (Minolta und mein Kalibrierkandidat) wurden auf gleiche Ebene gebracht (wichtig!) und fixiert. Das Netzteil kann Spannungs- und Stromsweeps, die für solch einen Zweck auf den ersten Blick perfekt geeignet sind. Also den Strom von 0 bis IIRC knapp 1,5 A in 400 Schritten zu je 2 Sekunden durchlaufen lassen, das Messgerät und Sensor mit etwas höherer Frequenz abfragen und in eine Log schreiben lassen. Das Ganze mit allen möglichen Konfigurationen des ALS. Excel auf dem großen PC macht den Rest. Naja, denkste. Die Helligkeit ging alles andere als linear hoch. Die Daten habe ich direkt weggeworfen und die Messung erneut mit Variation Spannung laufen lassen - entgegen dem allgemeinen Glauben ging die Helligkeit linear hoch. Trotzdem ist und bleibt die Regel: LEDs über Stromquellen versorgen. Die Gründe breite ich hier jetzt nicht aus. Dort die beiden Helligkeitswerte im X-Y-Diagramm auftragen lassen und feststellen, dass der Sensor fernab von dem ist, was zu erwarten ist. Genauso sind die Daten in der Hinsicht etwas ungeschickt zum Auswerten, dass es für jede tatsächliche Helligkeit mehrere Wertepaare gibt. Gleichzeitig gibt es aber auch (erwartungsgemäß) ungültige Wertpaare, da ein Sensor vor und der andere nach dem Umschalten der Spannung ausgelesen wurde. Die ganzen Messartefakte kann man zwar filtern, aber das ist unnötig und nervig. Nachdem die ganzen Messungen durch waren, musste das Luxmeter auch schon wieder zurück in die Arbeit. Nachdem der erste Lauf vielversprechend war, glaube ich, dass die anderen Messungen ok waren. Zudem war es viel zu heiß (Sommer 2015), um im Büro zu sitzen. Long story short: ein kleiner Programmierfehler und die Integrationszeiten wurden nicht in den Sensor geschrieben. <gallery> Datei:apds9300_diag_1_1.png|Verstärkung = 1; Integrationszeit = 13,7ms Datei:apds9300_diag_1_2.png|Verstärkung = 16; Integrationszeit = 13,7ms </gallery> Aarrgghh! ==Versuch 2== Fehler darf man machen, solange man daraus lernt. Das Rigol kann USB, und für das Auslesen des ALS habe ich eine Schaltung mit dem [http://hobbyelektronik.org/b/2015/09/mcp2221/ MCP2221] aufgebaut. Die Lichtquelle bleibt die selbe, sie steckt aber nun in der Decke eines Schuhkartons. Dadurch kann der Abstand, Position und Helligkeit (Streulicht!) relativ gut definiert werden: <gallery> Datei:apds9300_box.png|Aufbau der Messbox </gallery> Software: Dieses Mal in C#. Das kenne ich halbwegs und mag es. ===Automatisierung=== Zur Ansteuerung vom Netzteil muss erst einmal [https://www.ni.com/visa/ NI VISA] installiert werden. Ich hasse es, ich liebe es. Ich hasse es, weil die VISA-Treiber ein riesiges Bollwerk sind und man beim ersten Versuch immer die falschen erwischt. Zudem gibt es einen schönen Bug, bei dem Windows nach deren Installation irgendwann anfängt, knapp 20 Minuten für den Login zu braucht. Den [http://digital.ni.com/public.nsf/allkb/814FEF952915137686257B6B006C5F4F?OpenDocument offiziellen Fix] habe ich selbst noch nicht getestet, mit der im [http://forums.ni.com/t5/LabVIEW/Issues-with-windows-7-after-Labview-2012-installation/m-p/2257858#M715816 NI-Forum] beschriebenen Vorgehensweise habe ich gute Erfahrungen gemacht. Dadurch macht man sich unter Umständen zwar [[wpde:LAN eXtensions for Instrumentation|LXI]] kaputt, was in den meisten Fällen eh nicht verwendet wird. Was ich an VISA liebe? [[wpde:SCPI|SCPI]]! Messautomatisierung ist etwas wirklich feines und nicht nur, weil man auf dem Weg in die Mittagspause noch kurz "MAHLZEIT" auf dem Multimeter anzeigen lassen kann. Mir hat es in der Arbeit bereits unbeschreiblich viel manuelle Messzeit erspart. Dazu kommt, dass die Wiederholbarkeit sehr gut ist. Wie auch immer, die Software ist schnell und hässlich - aber zweckmäßig - runtergerissen. Die Messungen sind zum Einstellen der Helligkeit der Lichtquelle synchronisiert und neben den deutlich besseren Ergebnissen kann ich zugleich meine Lichtquelle kalibrieren. Ein Messlauf dauert nicht ganz zwei Minuten, wegen der unterschiedlichen Integrationszeiten und den beiden möglichen Verstärkungsfaktoren mal 6 und schon hat man einen Sensor vermessen. ==Auswertung== Das ganze nochmal in Excel verwurstet und es sieht gar nicht mal so gut aus: <gallery> Datei:apds9300_diag_2_1.png|Messergebnisse 1. Sensor mit Gain = 1 Datei:apds9300_diag_2_2.png|Messergebnisse 1. Sensor mit Gain = 16 </gallery> Im ersten Diagramm sieht man, dass die Werte schön und nahezu linear nach oben gehen, allerdings ist da - je nach Integrationslänge ordentlich Faktor drauf. Bei der Ausgabe wurde die Integrationszeit nicht berücksichtigt. Die Einbrüche im zweiten Diagramm lassen sich durch die tatsächlichen Messwerte erklären: <gallery> Datei:apds9300_diag_2_3.png|Messwerte ohne und 16-facher Verstärkung </gallery> Kanal 0 geht bei 16-facher Verstärkung sehr früh in Sättigung - das ist alles. Ok, nun müssen die Helligkeitswerte noch richtig skaliert werden. Meine Vermutung geht stark in die Richtung, dass entweder die Lichtempfindlichkeit oder die Integrationszeit bei den Sensoren nicht ganz richtig sind. Man kann den Korrekturfaktor zwar auf die berechnete Helligkeit anwenden - dadurch dass es in den Berechnungen keine Offsets gibt, sollte das auch funktionieren. Mir ist es allerdings deutlich lieber, direkt die rohen Werte zu behandeln. Also die Messwerte skalieren, durch die Formel zur Berechnung der Helligkeit jagen und das Ergebnis vergleichen. Excel kann das relativ gut automatisch - mit der Zielwertsuche. Der Parameter dafür ist die prozentuale Abweichung der berechneten Helligkeit und der Referenzmessung vom Luxmeter. Damit das Ganze funktioniert, muss der Algorithmus zur Berechnung in Excel implementiert werden. Ich habe aufgehört zu zählen... Unter Berücksichtigung der Integrationszeiten ergibt sich ein Faktor von relativ genau 0,2, um auf die "richtige" Helligkeit zu kommen. Zum Vermessen des zweiten Sensors habe ich diesen Faktor für die Berechnung des ausgegebenen Wertes in meine Software eingetragen und es kommt relativ gut hin - über den kompletten Messbereich war die Abweichung nicht größer als 5 %. Selbstverständlich ist das statistisch nicht aussagekräftig aber trotzdem eine Bestätigung, dass die ganze Aktion nicht grob falsch war. Die Erkenntnisse sind auch direkt in die C#-Software gewandert. Mit dieser kann im aktuellen Zustand die Helligkeit angezeigt werden. ="Kalibrierung" der Lichtquelle= Das Luxmeter musste ich selbstverständlich zurückgeben, aber was nun, wenn plötzlich und völlig unerwartet wieder ein Lichtsensor auf dem Tisch liegt und getestet werden muss, ob er richtig liegt, wenn das Licht angeht? Warum nicht einfach schauen, wie stabil die Lichtquelle ist? Natürlich ist der 15-Minuten-Aufbau nichts, was man für professionelle Zwecke auch nur in Erwägung ziehen würde, aber für den Heimbedarf - und um einen groben Anhaltspunkt zu finden: warum nicht? LEDs verändern sich in ihrem Leben. Wie sie bei Umgebungstemperatur altern: da habe ich kein wirkliches Gefühl. Allerdings weiß ich sehr genau, dass sie mit der Betriebszeit und durch Temperatur altern. Zugleich können sie ihre momentane Ausbeuten durch Erwärmung verändern. Da der Aufbau vermutlich nur für kurze Tests verwendet werden soll, kann die "Abnutzung" durch Betriebsdauer vernachlässigt werden. Anders ist es bei der Veränderung durch Betriebstemperatur. Allerdings kann man das relativ einfach testen: LEDs auf maximaler Leistung betrieben, Lichtsensor darunter packen und während den laufenden Messungen warten. Nach gut 20 Minuten (Länger ist das Ding wahrscheinlich eh nie am Stück im Betrieb) tat sich: nichts. Die LEDs sind offensichtlich stabil genug - oder die Messeinrichtung zu ungenau. Wer weiß. Auf jeden Fall habe ich jetzt eine zumindest grob brauchbare Ergebnisse, falls mal wieder ein Sensor vermessen werden will. =Leiterkarten= Ein paar der oben gezeigten Leiterkarte sind noch übrig. Wer will, kann eine haben. =Downloads= * [[Datei:apds9300.zip]] Alle Sourcen und Messdaten samt Auswertung. [[Kategorie:Elektronik]] [[Kategorie:PC]] [[Kategorie:Sensor]] 74804d7c09e9dc9baa82a27e8871a74ed233f308 1029 1027 2016-01-03T22:40:19Z Chris 2 Datelinks auf Bilder korrigiert wikitext text/x-wiki Vor einiger Zeit (genau genommen noch im Studium) wollte ich mit Lichtsensoren (ambient light sensors, ALS) spielen. Da ich bei Farnell bestellen konnte, kamen zwei Avago APDS-9300 mit auf das Bestellformular (Mittlerweile auch beim blauen Claus bzw. Völkner zu haben). Aufgrund der Bauform und Zeitmangel blieben sie relativ lange in der ESD-Tüte. =Der Sensor= Was soll man groß Worte über einen Lichtsensor verschwenden? Licht rein, aufbereitetes Signal raus und gut ist. Ganz so einfach ist es (zumindest beim APDS-9300) leider nicht. Viele optische Sensoren drehen bei Infrarot wild, das menschliche Auge zeichnet sich dagegen als ziemlich unempfindlich aus. In Digitalkameras werden aus diesem Grund IR-Filter verbaut (die Astrofotografen wieder entfernen), allerdings scheint das den Entwicklern bei Avago entweder zu teuer oder zu unpraktisch gewesen zu sein - sie haben zwei Fotodioden verbaut: Eine ist empfindlich auf das sichtbare Licht und Infrarot, die andere nur auf Infrarot (siehe Seite 7 vom Datenblatt). Der Rest ist Mathematik. Da die menschliche Wahrnehmung weitestgehend logarithmisch ist, braucht man zur Nachbildung einen großen Dynamikumfang. Daher kann der ALS mehrere Betriebsmodi. Zum einen kann man die Integrationszeit (also die Zeit, in der die Lichtdosis gesammelt wird) wählen - konkret zwischen 13,7 ms, 101 ms und 402 ms. Zum anderen kann man einen 16-fach-Verstärker zuschalten. Dadurch gewinnt man zwar Empfindlichkeit, bezahlt die aber mit der Auflösung und Rauschen. Die Wahl der richtigen Einstellung hängt selbstverständlich von der Umgebungshelligkeit ab, ansonsten liest man entweder 0 oder der bekommt Werte in der Sättigung, die einfach keinen Sinn ergeben. =Hardware= Bei der Fertigung meiner ersten Fuhre Leiterkarten bei DirtyPCBs landete auch ein kleines Breakout-Board auf dem Panel: <gallery> Datei:apds9300_sch.png|Schaltplan, Datei:apds9300_brd.png|Layout Datei:apds9300_asy.jpg|und aufgebautes Sensormodul </gallery> Neben dem Sensor selbst befindet sich aufgrund dessen etwas unpraktischen Versorgungsspannung ein 2,5 V-LDO-Spannungsregler. Die Wahl auf den LDO fiel, damit die Schaltung neben den eher altmodischen 5 V auch bei 3,3 V (und somit zum Beispiel mit dem Raspberry Pi) funktioniert. Als Schnittstelle dient bei dem Lichtsensor I²C, die Treiberstufen sind hier zwar zwangsläufig Open Drain und können deshalb in aller Regel etwas höhere Spannungen als die Betriebsspannung ab, bei den Eingangstufen bzw. ESD-Schutz wird es für das Bauteil bei höheren Spannungen ungemütlicher. ==Levelshifter== Damit man den I²C mit höherer Spannung betreiben kann, wird ein (bzw. eher zwei) Levelshifter benötigt. Diesen kann man entweder fertig kaufen oder mit nur wenigen Bauteilen aufbauen - [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] erklärt, wie es funktioniert. Für alle, die zu faul zum Klicken oder des Englischen nicht ganz so mächtig sind: Bei der Schaltung wird sowohl die Body-Diode als auch die schaltende Wirkung des FET genutzt (und als Beifang die Pull-Up-Widerstände, die man für I²C eh braucht). Das Schaltungsprinzip ist einfach wie genial: Wird keine der beiden Seiten auf Masse gezogen, ist U_GS nahezu 0 oder zumindest weit unter U_GS,th - der FET sperrt und dadurch dass die Spannung auf der Kathoden-Seite der Diode höher als auf der Anoden-Seite ist, sehen sich die Schaltungsteile nicht. Den Rest erledigen die Pull-ups. Wird auf der 3,3 V-Seite das Signal auf Masse gezogen, steigt U_GS über U_GS,th und der Transistor beginnt zu leiten. Dadurch sieht man auf der 5 V-Seite die Masse der 3,3 V-Seite. Szenario Nummer 3 ist nicht ganz so offensichtlich: Wird die 5 V-Seite auf Masse gezogen, fällt zunächst der Drain-Pin des FETs auf Masse. Jetzt kommt ein Teil vom Transistor ins Spiel, der einem manchmal einen Knoten ins Gehirn macht: Die Body-Diode. Ist auf deren Kathoden-Seite ein niedrigeres Potenzial als auf deren Anoden-Seite, wird sie leitfähig, somit zieht sie den Source-Pin ebenfalls gegen die Masse, die auf der Source-Seite anliegt. Gegen - nicht auf - da noch ein bisschen Vorwärtsspannung abfällt. Allerdings fällt steigt auch U_GS über U_GS,th (der zweite Knoten im Gehirn) und der FET wird leitfähig. Somit ist die Masse der 5 V-Seite auf der 3,3 V-Seite (relativ) sauber sichtbar. Fertig ist der pillepalle einfache bidirektionale Levelshifter. Einziger Nachteil: die Spannung "links" muss immer kleiner sein als die "rechts". Zudem ist man mit den Spannungspegeln begrenzt (zum einen durch U_GS,th des FET und zum anderen durch die U_f der Body-Diode). Übrigens kann man durch das Abklemmen des Gates die Seite mit der niedrigeren Spannung isolieren. =Software - der erste Versuch= Wie kann man relativ einfach mit I²C basteln? Bei denen im PC kommt man zumindest unter Windows nicht ran (und will es [http://www.paintyourdragon.com/?p=43vermutlich auch nicht]), bei Mikrocontrollern muss man erst Soft- und Hardware basteln - das ist aufwändig und fehleranfällig. Was liegt also näher, als den Raspberry Pi zu verwenden? Dort gibt es neben den [https://github.com/groeck/i2c-tools i2c-tools] auch eine Integration in Python. Da ich keine besonderen Erfahrungen mit letztere Sprache habe, möge man mir die Codequalität entschuldigen. apds9300.py ist eine Klasse, die die Kommunikation mit dem Sensor beinhaltet. Mit viewapds.py wird der Sensor im Halbsekunden-Takt ausgelesen und sowohl die rohen als auch der berechnete Wert ausgegeben. So viel zur Theorie. In der Praxis verwandelte sich die Verwunderung sehr schnell in Verzweiflung - es kamen einfach keine auch nur halbwegs sinnvollen Werte heraus. Zuerst hatte ich meine kläglichen Versuche in Python im Verdacht, nach mehrmaligem Überprüfen und neu schreiben stellte sich allerdings heraus, dass anscheinend etwas mit dem Chip oder Datenblatt nicht passt, denn ein Vergleich mit [[wpde:Lux_(Einheit)#Beispiele_typischer_Beleuchtungsst.C3.A4rken typischen Werten|Beispielen]] in Wikipedia sagte mir nur: du liegst falsch. Nach ein paar Recherchen stellte sich heraus, dass der APDS-9300 auf einem anderen Sensor basiert (oder zumindest nicht verleugenbare Ähnlichkeiten besitzt), dem TS256x von TAOS. Auch der physische Aufbau hat gewisse Ähnlichkeiten (und die Formeln zur Berechnung der Helligkeit ebenfalls). Zudem hatten auch schon andere das Problem mit den Berechnungen, nur gab es keine Lösung. =Kalibrierung= Da hilft nur noch eines: Kalibrieren. Nur gegen was? Die Helligkeitswerte aus dem oben erwähnten Wikipedia-Artikel kann man nicht so einfach und vor allem nicht so genau nachstellen, also muss entweder eine kalibrierte Lichtquelle her oder Vergleichsmessungen gemacht werden. Es liegen ja genügend "Messgeräte" in Form von Handy und Tablet herum. Mit einer [https://play.google.com/store/apps/details?id=com.notquitethem.android.luxmeter passenden App] bekommt man die Helligkeit mundgerecht angezeigt, nur: bei meinen HTC (Sensation, Flyer und [http://hobbyelektronik.org/b/2013/02/transplantation-geglueckt-patient-muss-sterben/ Explorer]) kann man nur zwischen heller Sommertag, bedeckter Sommertag und Zappenduster unterscheiden. Das LG-Handy war in der interessanten Zeit in Reparatur und das Samsung-Tablet hatte zwar eine sehr hohe Auflösung aber dafür eine völlig unbrauchbare Winkelabhängigkeit. Ich habe mir sogar überlegt, mit der Fotokamera zu messen. Aber wie zum Henker kommt man von Blende, Belichtungszeit, Bildempfindlichkeit und Bildausschnitt auf einen brauchbaren Helligkeitswert in Lux? Nachdem die Granularität durch die festen Schritte bei den drei ersten Parametern recht schlecht ist und die Messung durch den Bildausschnitt noch heikler wird, habe ich es bei der Idee belassen. Es muss also ein geeignetes Messgerät her. Nur für das Vermessen eines Sensors Messequipment kaufen (das den Sensor auch gleich ersetzt)? Muss nicht sein: ==Minolta T-10== In der Arbeit ist u. a. ein portables Luxmeter vorhanden und ich durfte es mir freundlicherweise für zwei Wochenenden ausleihen. Das Teil hat eine RS-232-Schnittstelle, wenn auch mit einem etwas komischen Stecker. Nach der Protokollbeschreibung muss man etwas suchen, allerdings ist die Implementierung (abgesehen vom etwas verschwurbelten Ausgabeformat) relativ einfach zu bewerkstelligen. Wer in die Verlegenheit kommt, so ein T-10 (oder vergleichbare Modelle) auszulesen: unten in den Downloads gibt es sowohl für Python als auch C# Quelltexte. ==Versuch 1== Der Messaufbau umfasst: * ALS und Luxmeter (über USB-RS232-Wandler) am Pi * eine windig zusammengebaute Lichtquelle aus LED-Streifen, Kühlkörper und Diffusor aus einem alten Notebook-Display. * Ein Rigol DP832 als Spannungsquelle * Eine Metallschiene sowie ein Pappkarton zum Aufbauen eines "Lichtgalgen" Beide Lichtsensoren (Minolta und mein Kalibrierkandidat) wurden auf gleiche Ebene gebracht (wichtig!) und fixiert. Das Netzteil kann Spannungs- und Stromsweeps, die für solch einen Zweck auf den ersten Blick perfekt geeignet sind. Also den Strom von 0 bis IIRC knapp 1,5 A in 400 Schritten zu je 2 Sekunden durchlaufen lassen, das Messgerät und Sensor mit etwas höherer Frequenz abfragen und in eine Log schreiben lassen. Das Ganze mit allen möglichen Konfigurationen des ALS. Excel auf dem großen PC macht den Rest. Naja, denkste. Die Helligkeit ging alles andere als linear hoch. Die Daten habe ich direkt weggeworfen und die Messung erneut mit Variation Spannung laufen lassen - entgegen dem allgemeinen Glauben ging die Helligkeit linear hoch. Trotzdem ist und bleibt die Regel: LEDs über Stromquellen versorgen. Die Gründe breite ich hier jetzt nicht aus. Dort die beiden Helligkeitswerte im X-Y-Diagramm auftragen lassen und feststellen, dass der Sensor fernab von dem ist, was zu erwarten ist. Genauso sind die Daten in der Hinsicht etwas ungeschickt zum Auswerten, dass es für jede tatsächliche Helligkeit mehrere Wertepaare gibt. Gleichzeitig gibt es aber auch (erwartungsgemäß) ungültige Wertpaare, da ein Sensor vor und der andere nach dem Umschalten der Spannung ausgelesen wurde. Die ganzen Messartefakte kann man zwar filtern, aber das ist unnötig und nervig. Nachdem die ganzen Messungen durch waren, musste das Luxmeter auch schon wieder zurück in die Arbeit. Nachdem der erste Lauf vielversprechend war, glaube ich, dass die anderen Messungen ok waren. Zudem war es viel zu heiß (Sommer 2015), um im Büro zu sitzen. Long story short: ein kleiner Programmierfehler und die Integrationszeiten wurden nicht in den Sensor geschrieben. <gallery> Datei:apds9300_diag_1_1.png|Verstärkung = 1; Integrationszeit = 13,7ms Datei:apds9300_diag_1_2.png|Verstärkung = 16; Integrationszeit = 13,7ms </gallery> Aarrgghh! ==Versuch 2== Fehler darf man machen, solange man daraus lernt. Das Rigol kann USB, und für das Auslesen des ALS habe ich eine Schaltung mit dem [http://hobbyelektronik.org/b/2015/09/mcp2221/ MCP2221] aufgebaut. Die Lichtquelle bleibt die selbe, sie steckt aber nun in der Decke eines Schuhkartons. Dadurch kann der Abstand, Position und Helligkeit (Streulicht!) relativ gut definiert werden: <gallery> Datei:apds9300_box.jpg|Aufbau der Messbox </gallery> Software: Dieses Mal in C#. Das kenne ich halbwegs und mag es. ===Automatisierung=== Zur Ansteuerung vom Netzteil muss erst einmal [https://www.ni.com/visa/ NI VISA] installiert werden. Ich hasse es, ich liebe es. Ich hasse es, weil die VISA-Treiber ein riesiges Bollwerk sind und man beim ersten Versuch immer die falschen erwischt. Zudem gibt es einen schönen Bug, bei dem Windows nach deren Installation irgendwann anfängt, knapp 20 Minuten für den Login zu braucht. Den [http://digital.ni.com/public.nsf/allkb/814FEF952915137686257B6B006C5F4F?OpenDocument offiziellen Fix] habe ich selbst noch nicht getestet, mit der im [http://forums.ni.com/t5/LabVIEW/Issues-with-windows-7-after-Labview-2012-installation/m-p/2257858#M715816 NI-Forum] beschriebenen Vorgehensweise habe ich gute Erfahrungen gemacht. Dadurch macht man sich unter Umständen zwar [[wpde:LAN eXtensions for Instrumentation|LXI]] kaputt, was in den meisten Fällen eh nicht verwendet wird. Was ich an VISA liebe? [[wpde:SCPI|SCPI]]! Messautomatisierung ist etwas wirklich feines und nicht nur, weil man auf dem Weg in die Mittagspause noch kurz "MAHLZEIT" auf dem Multimeter anzeigen lassen kann. Mir hat es in der Arbeit bereits unbeschreiblich viel manuelle Messzeit erspart. Dazu kommt, dass die Wiederholbarkeit sehr gut ist. Wie auch immer, die Software ist schnell und hässlich - aber zweckmäßig - runtergerissen. Die Messungen sind zum Einstellen der Helligkeit der Lichtquelle synchronisiert und neben den deutlich besseren Ergebnissen kann ich zugleich meine Lichtquelle kalibrieren. Ein Messlauf dauert nicht ganz zwei Minuten, wegen der unterschiedlichen Integrationszeiten und den beiden möglichen Verstärkungsfaktoren mal 6 und schon hat man einen Sensor vermessen. ==Auswertung== Das ganze nochmal in Excel verwurstet und es sieht gar nicht mal so gut aus: <gallery> Datei:apds9300_diag_2_1.png|Messergebnisse 1. Sensor mit Gain = 1 Datei:apds9300_diag_2_2.png|Messergebnisse 1. Sensor mit Gain = 16 </gallery> Im ersten Diagramm sieht man, dass die Werte schön und nahezu linear nach oben gehen, allerdings ist da - je nach Integrationslänge ordentlich Faktor drauf. Bei der Ausgabe wurde die Integrationszeit nicht berücksichtigt. Die Einbrüche im zweiten Diagramm lassen sich durch die tatsächlichen Messwerte erklären: <gallery> Datei:apds9300_diag_2_3.png|Messwerte ohne und 16-facher Verstärkung </gallery> Kanal 0 geht bei 16-facher Verstärkung sehr früh in Sättigung - das ist alles. Ok, nun müssen die Helligkeitswerte noch richtig skaliert werden. Meine Vermutung geht stark in die Richtung, dass entweder die Lichtempfindlichkeit oder die Integrationszeit bei den Sensoren nicht ganz richtig sind. Man kann den Korrekturfaktor zwar auf die berechnete Helligkeit anwenden - dadurch dass es in den Berechnungen keine Offsets gibt, sollte das auch funktionieren. Mir ist es allerdings deutlich lieber, direkt die rohen Werte zu behandeln. Also die Messwerte skalieren, durch die Formel zur Berechnung der Helligkeit jagen und das Ergebnis vergleichen. Excel kann das relativ gut automatisch - mit der Zielwertsuche. Der Parameter dafür ist die prozentuale Abweichung der berechneten Helligkeit und der Referenzmessung vom Luxmeter. Damit das Ganze funktioniert, muss der Algorithmus zur Berechnung in Excel implementiert werden. Ich habe aufgehört zu zählen... Unter Berücksichtigung der Integrationszeiten ergibt sich ein Faktor von relativ genau 0,2, um auf die "richtige" Helligkeit zu kommen. Zum Vermessen des zweiten Sensors habe ich diesen Faktor für die Berechnung des ausgegebenen Wertes in meine Software eingetragen und es kommt relativ gut hin - über den kompletten Messbereich war die Abweichung nicht größer als 5 %. Selbstverständlich ist das statistisch nicht aussagekräftig aber trotzdem eine Bestätigung, dass die ganze Aktion nicht grob falsch war. Die Erkenntnisse sind auch direkt in die C#-Software gewandert. Mit dieser kann im aktuellen Zustand die Helligkeit angezeigt werden. ="Kalibrierung" der Lichtquelle= Das Luxmeter musste ich selbstverständlich zurückgeben, aber was nun, wenn plötzlich und völlig unerwartet wieder ein Lichtsensor auf dem Tisch liegt und getestet werden muss, ob er richtig liegt, wenn das Licht angeht? Warum nicht einfach schauen, wie stabil die Lichtquelle ist? Natürlich ist der 15-Minuten-Aufbau nichts, was man für professionelle Zwecke auch nur in Erwägung ziehen würde, aber für den Heimbedarf - und um einen groben Anhaltspunkt zu finden: warum nicht? LEDs verändern sich in ihrem Leben. Wie sie bei Umgebungstemperatur altern: da habe ich kein wirkliches Gefühl. Allerdings weiß ich sehr genau, dass sie mit der Betriebszeit und durch Temperatur altern. Zugleich können sie ihre momentane Ausbeuten durch Erwärmung verändern. Da der Aufbau vermutlich nur für kurze Tests verwendet werden soll, kann die "Abnutzung" durch Betriebsdauer vernachlässigt werden. Anders ist es bei der Veränderung durch Betriebstemperatur. Allerdings kann man das relativ einfach testen: LEDs auf maximaler Leistung betrieben, Lichtsensor darunter packen und während den laufenden Messungen warten. Nach gut 20 Minuten (Länger ist das Ding wahrscheinlich eh nie am Stück im Betrieb) tat sich: nichts. Die LEDs sind offensichtlich stabil genug - oder die Messeinrichtung zu ungenau. Wer weiß. Auf jeden Fall habe ich jetzt eine zumindest grob brauchbare Ergebnisse, falls mal wieder ein Sensor vermessen werden will. =Leiterkarten= Ein paar der oben gezeigten Leiterkarte sind noch übrig. Wer will, kann eine haben. =Downloads= * [[Datei:apds9300.zip]] Alle Sourcen und Messdaten samt Auswertung. [[Kategorie:Elektronik]] [[Kategorie:PC]] [[Kategorie:Sensor]] 9ed3dd8e6e26a08dd5c2af983b43e6ae00885b1c APDS-9300 0 429 1026 2016-01-02T14:36:30Z Chris 2 verschob „[[APDS-9300]]“ nach „[[Lichtsensor Avago APDS-9300]]“: besserer Seitentitel wikitext text/x-wiki #WEITERLEITUNG [[Lichtsensor Avago APDS-9300]] a57cbb06b70395300434d7a97db31843b16768ca Datei:Vbus rxo brd.png 6 430 1030 2016-03-11T22:12:11Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbus rxo.zip 6 431 1031 2016-03-11T22:20:00Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder 0 120 1032 904 2016-03-11T22:20:31Z Chris 2 Hardware für den PC hinzugefügt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= [[Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware]] Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegal und die Versorgung wird vom VBus übernommen. Die Daten für EAGLE befinden sich im Download-Bereich. =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] 567797d0aefd4b62a25b2f8c5c15ae7e84b6fb2f Physik-Formelsammlung 0 229 1034 611 2016-03-11T22:28:16Z Chris 2 Fehler/Unklares wikitext text/x-wiki Irgendwann im ersten Semester bin ich auf die Idee gekommen, eine Formelsammlung für Physik zu schreiben, die genau die Anforderungen für die Klausur entspricht. Markus (ein Kommilitone) hat sie im zweiten Semester fortgeführt und ich schließlich ergänzt. = Inhalt = Die Formelsammlung umfasst so ziemlich alles, was man in den ersten beiden Semstern Physik im Studiengang Elektrotechnik (zumindest an der Hochschule Ulm) benötigt. Dies ist u. a.: # Grundlagen ## Die wichtigsten Werte auf einen Blick ## Atom ## Additionstheoreme # Punktmechanik ## Kinematik ### Geradlinige Bewegung (Translation) ### Gleichmäßig beschleunigte Bewegung (Translation) ### Würfe (Translation) ### Kreisbewegung (Rotation) ### Übersetzungstabelle Translation ? Rotation ## Dynamik ### Impulssatz (Translation) ### Kraftbegriff ### Kräfte ### Trägheitskräfte ## Energie ### Begriffe ### Stöße ## Himmelsmechanik # Mechanik der starren Körper ## Statik ### Gleichgewichtsbedingung ### Schwerpunkt ## Dynamik starrer Körper ### Schwerpunktbewegung # Materie in Feldern ## Elektrisches Feld ### Allgemein ### Dipol ### Kondensator ### Schaltvorgänge ### Dielektrika ### Leitende Materialien ### Leitung in Flüssigkeit ### Leitung in Gasen ## Magnetisches Feld ### Analogie ## Bewegung im homogenen Feld ## Lange gerade Leiter ## Verschieden Leiter ### Allgemein ### Lange Spule (Solenoid)/Toroidspule (Ring) ### Mitte einer Kreisschleife/Kurze Spule (L«D) ### Beliebige Spule ## Magnetisches Dipolmoment (Spin, Eigendrehimpuls eines Atoms) ### Kenngrößen ### Hall-Effekt # Induktion ## Induktionsgesetz ## Anwendungen ## Schaltvorgänge # Schwingungen ## Harmonischer Oszillator ### Pohlsches Rad ## Gedämpfte Schwingung ### Mechanisch ### Elektrisch ## Schwinger mit Anregung # Wellen ## Grundwissen ## Polarisation ## Wellengleichung ## Dopplereffekt ## Stehende Welle ## Interferenz und Beugung am Spalt ## Wellenoptik ## Dipolstrahlung ### Nahfeld ### Fernfeld # Statistik ## Gastherorie # Quantenphysik ## Allgemein ## Materialwellen ## Gebundene Zustände ## Wasserstoffatom ### Wichtige Energieübergänge ## Bändermodell ### Eigenhalbleiter ### Dotierte Halbleiter # Festkörper ## Halbleiter ### Homogene Halbleiter ### Heterogene Halbleiter = Download = Obwohl wir und unsere Dozenten gründlich gearbeitet haben, können wir keine Garantie für die Richtigkeit übernehmen. Solltest du Fehler finden, lass es [[Benutzer:Chris|mich]] bitte wissen. [[Datei:Physik-Formelsammlung.pdf]] (Stand: 19.03.2011) = Fehler/Unklares = * 1/2016: Marcel hat mich darauf aufmerksam gemacht, dass in Kapitel 4.1.3 Kondensator unter Energiedichte der Vektor der Feldstärke <math>\vec{E}</math> quadriert sein sollte. Hab es in meinen Aufschrieben leider nicht mehr finden können. Kann das jemand bestätigen? [[Kategorie:Sonstiges]] dd9820f194f0a475bc4e8d2a9ec094fc6878c6ae Datei:Chirp asm bot.jpg 6 432 1035 2016-06-23T20:24:45Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Chirp asm top.jpg 6 433 1036 2016-06-23T20:24:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Chirp brd.png 6 434 1037 2016-06-23T20:25:06Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Chirp pot.jpg 6 435 1038 2016-06-23T20:25:16Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Chirp sch.png 6 436 1039 2016-06-23T20:25:28Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Chirp.zip 6 437 1040 2016-06-23T20:26:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Minichirp 0 438 1041 2016-06-23T20:34:03Z Chris 2 Seite erstellt wikitext text/x-wiki [[Datei:Chirp_pot.jpg|thumb|Minichirp in Lauerstellung]] Ich weiß gar nicht mehr, wie ich darauf gestoßen bin und eigentlich fühlen sich die Pflanzen in der näheren Umgebung nicht ganz unwohl (bis auf den Weihnachtsstern, der mir nach einer Woche verreckt ist). Trotzdem wollte ich einen [http://wemakethings.net/chirp/ Chirp] haben. Dabei handelt es sich eine von Mic von wemakethings.net designtes Stück Hardware, das man in die Erde der zu überwachenden Pflanze steckt, anlehnt und dann angezirpt wird, wenn man vergisst zu gießen. So richtig gut hat mir das Layout aber nicht gefallen - das geht sicher kleiner und vielleicht schicker! = Komponenten = Das Original verwendet bedrahtete Bauteile (Taster und Schallgeber), die zudem relativ groß sind. Reichelt als angepeilten Quelle für die Bauteile bietet alles Benötigte im SMD-Gehäuse an. Im Fall des Piepsers zwar etwas teurer aber man kann eben nicht alles haben. Beim Batteriehalter habe ich länger gehadert - der Blechstreifen-Typ ist zwar günstig und sehr kompakt aber die zweite Kontaktfläche der Batterie wäre die Leiterkarte. Das raubt zum einen Platz für Leiterbahnen und zum anderen oxidiert die verzinnte Oberfläche irgendwann. Das macht die Schaltung unzuverlässig. Vergolden kann man zwar, aber das muss man bezahlen. Okay, den besseren Batteriehalter zwar auch, aber unterm Strich kommt es wahrscheinlich billiger. Der Konnektor für das ISP- bzw. auch I²C-Interface (wenn man ihn dazuzählen will) soll auch kleiner werden. Eine Reihe an 6 Kontakten mit 1,27 mm Rastermaß muss reichen - das ist nicht nur kompakter, sondern man kann auch die üblichen Flachbandkabel direkt anlöten. Die Anschlussbelegung folgt der des 6-pinnigen ISP-Steckers. Schlussendlich bin ich bei folgender Materialliste gelandet: {| class="wikitable" ! Menge ! Wert ! Wert ! Bestellname Reichelt |- | 1 | LED1 | | LED EL 0603 GR1 |- | 1 | R2 | 100 | SMD-0603 100 |- | 2 | C1, C2 | 100n | X7R-G0603 100N |- | 4 | R1, R3, R4, R6 | 10k | SMD-0603 10k |- | 2 | C3, C4 | 1u | X7R-G0805 1,0/16 |- | 1 | R5 | 470k | SMD-0603 470K |- | 1 | IC1 | ATTINY44A | ATTINY 44A-SSU |- | 1 | D1 | BAT54 | BAT 54 SMD |- | 1 | Q1 | BSS138 | BSS 138 SMD |- | 1 | S1 | KMR2 | KMR 231 G LFS |- | 1 | X2 | KZH20SMD-2 | KZH 20SMD-2 |- | 1 | SG2 | SMD-08A03 | SMD-08A03 |} = Layout = Eine feste Größe der Leiterkarte habe ich nicht vorgegeben, nur ein paar Einschränkungen und Ziele: Fläche so gut ausnutzen wie möglich (und dadurch so klein wie möglich werden) und die längere Kante sollte höchstens 10 cm sein - damit es zum einen in EAGLE Light geroutet werden kann und die Produktion in Fernost günstig bleibt. Die Platzierung ist geradeaus: der Batteriehalter ist am größten und nimmt die Unterseite in Beschlag, oben kommt der ganze Rest. Alles was den Benutzer betrifft, kommt ans Ende: Buzzer, LED, Taster und Schnittstelle, damit das Zeug möglichst weit von der feuchten Erde weg ist. Der Mikrocontroller samt einer Reihe Bauteile ist ca. 10 mm breit, das Ziel für die Breite der Leiterkarte somit auf "ein bisschen mehr" gesteckt. Dem geschuldet wandert die LED auf die Unterseite und der Batteriehalter samt Batterie schaut recht großzügig heraus. Nicht ganz optimal aber die Leiterkarte bleibt klein. Die Sensorfläche ist deutlich größer als beim Original - ob und welchen Einfluss das auf die Messung hat, muss ich noch herausfinden. Da die Software adaptiv arbeitet, sollte sie damit aber klar kommen. Im Bereich der in die Erde kommt, sind bewusst keine Vias. Auch wenn dadurch die zwei Masseflächen elektrisch gesehen etwas voneinander abdriften: oft schaut bei den Bohrungen das Kupfer heraus. Zwar soll Kupfer Schnittblumen helfen, länger frisch zu bleiben, die Auswirkungen auf andere Pflanzen muss ich damit aber nicht unbedingt herausfinden. Zudem dürften die Durchkontaktierungen mit der Zeit Korrosionen zum Opfer fallen - dann kann man sie sich auch gleich sparen. Offen bleibt jedoch die Frage, wie sich der Lötstopplack mit Erde und Feuchtigkeit verträgt (oder andersrum: wie die Pflanze die Chemie abkann). Auch auf der Seite von wemakethings steht dazu leider nichts. Ein weiteres Detail ist die runde Spitze auf Sensorseite - diese soll das Einstecken in den Topf erleichtern. Analogie (schlechter Wortwitz inbegriffen): Nein, kein Fieberthermometer, sondern diese Einsteckkärtchen, die man oft in Pflanzkübeln findet. Nach ein paar Stunden Grübeln steht das Layout. Zufrieden ist man natürlich nie, aber es hätte auch schlechter sein können: <gallery> Datei:Chirp_sch.png|Schaltplan des Minichirp Datei:Chirp_brd.png|Layout des Minchirp </gallery> = Aufbau = Der Aufbau ist weitestgehend harmlos. Lediglich an einer Stelle ist es ziemlich eng: das nicht genutzte Eck vom Signalgeber kommt den Pads vom Taster gefährlich nahe und obwohl ich mich beim Footprint des kleinen Lautsprechers an das Datenblatt gehalten habe, scheinen die Pins nicht ganz auf die Pads zu passen. Beim Bestücken sollte man jedoch darauf achten, den Taster vor dem Piepser aufzulöten und den Batteriehalter als allerletztes einzulöten. Zum einen, weil sonst die Lötspitze zu stinken anfängt, zum anderen, weil Piepser und Batteriehalter die klobigsten Komponenten sind und sie dadurch das Löten der anderen Bauteile deutlich erschweren. {{Infobox AVR | Typ = ATtiny44 | Takt = 1 | FuseH = DE | FuseL = E2 }} Zum Flashen muss ein Flachbandkabel an den Konnektor, mit nicht eingelegter Batterie können Fuses und Flash geschrieben werden, zumindest wenn man die passende Hexfile hat. Auf Github liegt sie zumindest nicht, also den Compiler selbst anwerfen. <gallery> Datei:Chirp_asm_top.jpg|Von oben... Datei:Chirp_asm_bot.jpg|...und unten </gallery> = Bedienung = Kurz nachdem die Firmware auf dem Controller gelandet ist, fängt das Teil auch an zu Zirpen. Was ich nicht wusste: wenn nichts im EEPROM steht, wird über die LED auch gleich die Referenzhelligkeit gemessen und abgelegt. Später wird erst ab diesem Wert gezirpt. Grundlegend keine schlechte Idee, nur war zu diesem Zeitpunkt die Schreibtischleuchte perfekt auf die LED ausgerichtet. Im etwas dunkleren Wohnzimmer wurde dann geblinkt statt gezirpt. Also die gerade abgeknipste Leitung wieder anlöten, und den EEPROM löschen. So viel vom ersten Fallstrick bei der Bedienung. Ansonsten ist das Teil einfach zu bedienen: Nach dem ersten Einschalten oder dem Drücken des (Re-)Set-Tasters wird die "Trocken-Feuchtigkeit" gemessen, also jene wenn man die Pflanze gießen sollte. Die Messung wird nach ca. 5 Sekunden mit einem längeren Zirpen quittiert. Anschließend kann man die Pflanze (aber nicht den Chirp) mit Wasser versorgen. Die Elektronik wacht immer wieder auf und misst die Kapazität der Sensorfläche. Wird eine zu niedrige Feuchtigkeit ermittelt, legt bei Helligkeit die zirpende Grille los (nein, nicht [https://www.youtube.com/results?search_query=zirpende+Grille+MIB die]). Bei Dunkelheit wird man durch die LED benachrichtigt. Erkennt der Mikrocontroller, dass die Feuchtigkeit gestiegen ist, wird das Gießen wiederum mit einem länglichen Zirpen bestätigt. Nachdem die erste Woche bei meinen widerstandsfähigeren Topfpflanzen (die für den ersten Test herhalten mussten) vorbei war, wurde ich etwas ungeduldig. Kein Zirpen. Einen Tag später legte sie aber los. Nicht zu laut aber dennoch gut hörbar. Bis jetzt sehr zuverlässig. = Lizenz = Das Originalprojekt ist unter der CERN OHL 1.1 lizenziert. Der Einfachheit halber ziehe ich gleich. = Download = * [[Chirp.zip]] = Wer will? = Es gibt noch ein paar der Leiterkarten. Wer eine will, kann sie gerne kostenlos aber gegen Versandkosten haben. Und nein: ich verkaufe keine fertig bestückten Chirps. Vielleicht übernimmt ja Mic mein Layout und bietet es auf Tindie an!? [[Category:AVR]] cf79c029c380f2eee53713ccbd73a7adf816eb29 1042 1041 2016-06-23T20:39:14Z Chris 2 Tabelle und Link auf Zip korrigiert. wikitext text/x-wiki [[Datei:Chirp_pot.jpg|thumb|Minichirp in Lauerstellung]] Ich weiß gar nicht mehr, wie ich darauf gestoßen bin und eigentlich fühlen sich die Pflanzen in der näheren Umgebung nicht ganz unwohl (bis auf den Weihnachtsstern, der mir nach einer Woche verreckt ist). Trotzdem wollte ich einen [http://wemakethings.net/chirp/ Chirp] haben. Dabei handelt es sich eine von Mic von wemakethings.net designtes Stück Hardware, das man in die Erde der zu überwachenden Pflanze steckt, anlehnt und dann angezirpt wird, wenn man vergisst zu gießen. So richtig gut hat mir das Layout aber nicht gefallen - das geht sicher kleiner und vielleicht schicker! = Komponenten = Das Original verwendet bedrahtete Bauteile (Taster und Schallgeber), die zudem relativ groß sind. Reichelt als angepeilten Quelle für die Bauteile bietet alles Benötigte im SMD-Gehäuse an. Im Fall des Piepsers zwar etwas teurer aber man kann eben nicht alles haben. Beim Batteriehalter habe ich länger gehadert - der Blechstreifen-Typ ist zwar günstig und sehr kompakt aber die zweite Kontaktfläche der Batterie wäre die Leiterkarte. Das raubt zum einen Platz für Leiterbahnen und zum anderen oxidiert die verzinnte Oberfläche irgendwann. Das macht die Schaltung unzuverlässig. Vergolden kann man zwar, aber das muss man bezahlen. Okay, den besseren Batteriehalter zwar auch, aber unterm Strich kommt es wahrscheinlich billiger. Der Konnektor für das ISP- bzw. auch I²C-Interface (wenn man ihn dazuzählen will) soll auch kleiner werden. Eine Reihe an 6 Kontakten mit 1,27 mm Rastermaß muss reichen - das ist nicht nur kompakter, sondern man kann auch die üblichen Flachbandkabel direkt anlöten. Die Anschlussbelegung folgt der des 6-pinnigen ISP-Steckers. Schlussendlich bin ich bei folgender Materialliste gelandet: {| class="wikitable" ! Menge !! Name !! Wert !! Bestellname Reichelt |- | 1 || LED1 || || LED EL 0603 GR1 |- | 1 || R2 || 100 || SMD-0603 100 |- | 2 || C1, C2 || 100n || X7R-G0603 100N |- | 4 || R1, R3, R4, R6 || 10k || SMD-0603 10k |- | 2 || C3, C4 || 1u || X7R-G0805 1,0/16 |- | 1 || R5 || 470k || SMD-0603 470K |- | 1 || IC1 || ATTINY44A || ATTINY 44A-SSU |- | 1 || D1 || BAT54 || BAT 54 SMD |- | 1 || Q1 || BSS138 || BSS 138 SMD |- | 1 || S1 || KMR2 || KMR 231 G LFS |- | 1 || X2 || KZH20SMD-2 || KZH 20SMD-2 |- | 1 || SG2 || SMD-08A03 || SMD-08A03 |} = Layout = Eine feste Größe der Leiterkarte habe ich nicht vorgegeben, nur ein paar Einschränkungen und Ziele: Fläche so gut ausnutzen wie möglich (und dadurch so klein wie möglich werden) und die längere Kante sollte höchstens 10 cm sein - damit es zum einen in EAGLE Light geroutet werden kann und die Produktion in Fernost günstig bleibt. Die Platzierung ist geradeaus: der Batteriehalter ist am größten und nimmt die Unterseite in Beschlag, oben kommt der ganze Rest. Alles was den Benutzer betrifft, kommt ans Ende: Buzzer, LED, Taster und Schnittstelle, damit das Zeug möglichst weit von der feuchten Erde weg ist. Der Mikrocontroller samt einer Reihe Bauteile ist ca. 10 mm breit, das Ziel für die Breite der Leiterkarte somit auf "ein bisschen mehr" gesteckt. Dem geschuldet wandert die LED auf die Unterseite und der Batteriehalter samt Batterie schaut recht großzügig heraus. Nicht ganz optimal aber die Leiterkarte bleibt klein. Die Sensorfläche ist deutlich größer als beim Original - ob und welchen Einfluss das auf die Messung hat, muss ich noch herausfinden. Da die Software adaptiv arbeitet, sollte sie damit aber klar kommen. Im Bereich der in die Erde kommt, sind bewusst keine Vias. Auch wenn dadurch die zwei Masseflächen elektrisch gesehen etwas voneinander abdriften: oft schaut bei den Bohrungen das Kupfer heraus. Zwar soll Kupfer Schnittblumen helfen, länger frisch zu bleiben, die Auswirkungen auf andere Pflanzen muss ich damit aber nicht unbedingt herausfinden. Zudem dürften die Durchkontaktierungen mit der Zeit Korrosionen zum Opfer fallen - dann kann man sie sich auch gleich sparen. Offen bleibt jedoch die Frage, wie sich der Lötstopplack mit Erde und Feuchtigkeit verträgt (oder andersrum: wie die Pflanze die Chemie abkann). Auch auf der Seite von wemakethings steht dazu leider nichts. Ein weiteres Detail ist die runde Spitze auf Sensorseite - diese soll das Einstecken in den Topf erleichtern. Analogie (schlechter Wortwitz inbegriffen): Nein, kein Fieberthermometer, sondern diese Einsteckkärtchen, die man oft in Pflanzkübeln findet. Nach ein paar Stunden Grübeln steht das Layout. Zufrieden ist man natürlich nie, aber es hätte auch schlechter sein können: <gallery> Datei:Chirp_sch.png|Schaltplan des Minichirp Datei:Chirp_brd.png|Layout des Minchirp </gallery> = Aufbau = Der Aufbau ist weitestgehend harmlos. Lediglich an einer Stelle ist es ziemlich eng: das nicht genutzte Eck vom Signalgeber kommt den Pads vom Taster gefährlich nahe und obwohl ich mich beim Footprint des kleinen Lautsprechers an das Datenblatt gehalten habe, scheinen die Pins nicht ganz auf die Pads zu passen. Beim Bestücken sollte man jedoch darauf achten, den Taster vor dem Piepser aufzulöten und den Batteriehalter als allerletztes einzulöten. Zum einen, weil sonst die Lötspitze zu stinken anfängt, zum anderen, weil Piepser und Batteriehalter die klobigsten Komponenten sind und sie dadurch das Löten der anderen Bauteile deutlich erschweren. {{Infobox AVR | Typ = ATtiny44 | Takt = 1 | FuseH = DE | FuseL = E2 }} Zum Flashen muss ein Flachbandkabel an den Konnektor, mit nicht eingelegter Batterie können Fuses und Flash geschrieben werden, zumindest wenn man die passende Hexfile hat. Auf Github liegt sie zumindest nicht, also den Compiler selbst anwerfen. <gallery> Datei:Chirp_asm_top.jpg|Von oben... Datei:Chirp_asm_bot.jpg|...und unten </gallery> = Bedienung = Kurz nachdem die Firmware auf dem Controller gelandet ist, fängt das Teil auch an zu Zirpen. Was ich nicht wusste: wenn nichts im EEPROM steht, wird über die LED auch gleich die Referenzhelligkeit gemessen und abgelegt. Später wird erst ab diesem Wert gezirpt. Grundlegend keine schlechte Idee, nur war zu diesem Zeitpunkt die Schreibtischleuchte perfekt auf die LED ausgerichtet. Im etwas dunkleren Wohnzimmer wurde dann geblinkt statt gezirpt. Also die gerade abgeknipste Leitung wieder anlöten, und den EEPROM löschen. So viel vom ersten Fallstrick bei der Bedienung. Ansonsten ist das Teil einfach zu bedienen: Nach dem ersten Einschalten oder dem Drücken des (Re-)Set-Tasters wird die "Trocken-Feuchtigkeit" gemessen, also jene wenn man die Pflanze gießen sollte. Die Messung wird nach ca. 5 Sekunden mit einem längeren Zirpen quittiert. Anschließend kann man die Pflanze (aber nicht den Chirp) mit Wasser versorgen. Die Elektronik wacht immer wieder auf und misst die Kapazität der Sensorfläche. Wird eine zu niedrige Feuchtigkeit ermittelt, legt bei Helligkeit die zirpende Grille los (nein, nicht [https://www.youtube.com/results?search_query=zirpende+Grille+MIB die]). Bei Dunkelheit wird man durch die LED benachrichtigt. Erkennt der Mikrocontroller, dass die Feuchtigkeit gestiegen ist, wird das Gießen wiederum mit einem länglichen Zirpen bestätigt. Nachdem die erste Woche bei meinen widerstandsfähigeren Topfpflanzen (die für den ersten Test herhalten mussten) vorbei war, wurde ich etwas ungeduldig. Kein Zirpen. Einen Tag später legte sie aber los. Nicht zu laut aber dennoch gut hörbar. Bis jetzt sehr zuverlässig. = Lizenz = Das Originalprojekt ist unter der CERN OHL 1.1 lizenziert. Der Einfachheit halber ziehe ich gleich. = Download = * [[Datei:Chirp.zip|Chirp.zip]] = Wer will? = Es gibt noch ein paar der Leiterkarten. Wer eine will, kann sie gerne kostenlos aber gegen Versandkosten haben. Und nein: ich verkaufe keine fertig bestückten Chirps. Vielleicht übernimmt ja Mic mein Layout und bietet es auf Tindie an!? [[Category:AVR]] 0c1cc0e3c57932b4ef466a5071573b99f7281dc1 Minichirp 0 438 1044 1042 2016-06-23T20:49:08Z Chris 2 dummes autocorrect. wikitext text/x-wiki [[Datei:Chirp_pot.jpg|thumb|Minichirp in Lauerstellung]] Ich weiß gar nicht mehr, wie ich darauf gestoßen bin und eigentlich fühlen sich die Pflanzen in der näheren Umgebung nicht ganz unwohl (bis auf den Weihnachtsstern, der mir nach einer Woche verreckt ist). Trotzdem wollte ich einen [http://wemakethings.net/chirp/ Chirp] haben. Dabei handelt es sich eine von Mic von wemakethings.net designtes Stück Hardware, das man in die Erde der zu überwachenden Pflanze steckt, anlernt und dann angezirpt wird, wenn man vergisst zu gießen. So richtig gut hat mir das Layout aber nicht gefallen - das geht sicher kleiner und vielleicht schicker! = Komponenten = Das Original verwendet bedrahtete Bauteile (Taster und Schallgeber), die zudem relativ groß sind. Reichelt als angepeilten Quelle für die Bauteile bietet alles Benötigte im SMD-Gehäuse an. Im Fall des Piepsers zwar etwas teurer aber man kann eben nicht alles haben. Beim Batteriehalter habe ich länger gehadert - der Blechstreifen-Typ ist zwar günstig und sehr kompakt aber die zweite Kontaktfläche der Batterie wäre die Leiterkarte. Das raubt zum einen Platz für Leiterbahnen und zum anderen oxidiert die verzinnte Oberfläche irgendwann. Das macht die Schaltung unzuverlässig. Vergolden kann man zwar, aber das muss man bezahlen. Okay, den besseren Batteriehalter zwar auch, aber unterm Strich kommt es wahrscheinlich billiger. Der Konnektor für das ISP- bzw. auch I²C-Interface (wenn man ihn dazuzählen will) soll auch kleiner werden. Eine Reihe an 6 Kontakten mit 1,27 mm Rastermaß muss reichen - das ist nicht nur kompakter, sondern man kann auch die üblichen Flachbandkabel direkt anlöten. Die Anschlussbelegung folgt der des 6-pinnigen ISP-Steckers. Schlussendlich bin ich bei folgender Materialliste gelandet: {| class="wikitable" ! Menge !! Name !! Wert !! Bestellname Reichelt |- | 1 || LED1 || || LED EL 0603 GR1 |- | 1 || R2 || 100 || SMD-0603 100 |- | 2 || C1, C2 || 100n || X7R-G0603 100N |- | 4 || R1, R3, R4, R6 || 10k || SMD-0603 10k |- | 2 || C3, C4 || 1u || X7R-G0805 1,0/16 |- | 1 || R5 || 470k || SMD-0603 470K |- | 1 || IC1 || ATTINY44A || ATTINY 44A-SSU |- | 1 || D1 || BAT54 || BAT 54 SMD |- | 1 || Q1 || BSS138 || BSS 138 SMD |- | 1 || S1 || KMR2 || KMR 231 G LFS |- | 1 || X2 || KZH20SMD-2 || KZH 20SMD-2 |- | 1 || SG2 || SMD-08A03 || SMD-08A03 |} = Layout = Eine feste Größe der Leiterkarte habe ich nicht vorgegeben, nur ein paar Einschränkungen und Ziele: Fläche so gut ausnutzen wie möglich (und dadurch so klein wie möglich werden) und die längere Kante sollte höchstens 10 cm sein - damit es zum einen in EAGLE Light geroutet werden kann und die Produktion in Fernost günstig bleibt. Die Platzierung ist geradeaus: der Batteriehalter ist am größten und nimmt die Unterseite in Beschlag, oben kommt der ganze Rest. Alles was den Benutzer betrifft, kommt ans Ende: Buzzer, LED, Taster und Schnittstelle, damit das Zeug möglichst weit von der feuchten Erde weg ist. Der Mikrocontroller samt einer Reihe Bauteile ist ca. 10 mm breit, das Ziel für die Breite der Leiterkarte somit auf "ein bisschen mehr" gesteckt. Dem geschuldet wandert die LED auf die Unterseite und der Batteriehalter samt Batterie schaut recht großzügig heraus. Nicht ganz optimal aber die Leiterkarte bleibt klein. Die Sensorfläche ist deutlich größer als beim Original - ob und welchen Einfluss das auf die Messung hat, muss ich noch herausfinden. Da die Software adaptiv arbeitet, sollte sie damit aber klar kommen. Im Bereich der in die Erde kommt, sind bewusst keine Vias. Auch wenn dadurch die zwei Masseflächen elektrisch gesehen etwas voneinander abdriften: oft schaut bei den Bohrungen das Kupfer heraus. Zwar soll Kupfer Schnittblumen helfen, länger frisch zu bleiben, die Auswirkungen auf andere Pflanzen muss ich damit aber nicht unbedingt herausfinden. Zudem dürften die Durchkontaktierungen mit der Zeit Korrosionen zum Opfer fallen - dann kann man sie sich auch gleich sparen. Offen bleibt jedoch die Frage, wie sich der Lötstopplack mit Erde und Feuchtigkeit verträgt (oder andersrum: wie die Pflanze die Chemie abkann). Auch auf der Seite von wemakethings steht dazu leider nichts. Ein weiteres Detail ist die runde Spitze auf Sensorseite - diese soll das Einstecken in den Topf erleichtern. Analogie (schlechter Wortwitz inbegriffen): Nein, kein Fieberthermometer, sondern diese Einsteckkärtchen, die man oft in Pflanzkübeln findet. Nach ein paar Stunden Grübeln steht das Layout. Zufrieden ist man natürlich nie, aber es hätte auch schlechter sein können: <gallery> Datei:Chirp_sch.png|Schaltplan des Minichirp Datei:Chirp_brd.png|Layout des Minchirp </gallery> = Aufbau = Der Aufbau ist weitestgehend harmlos. Lediglich an einer Stelle ist es ziemlich eng: das nicht genutzte Eck vom Signalgeber kommt den Pads vom Taster gefährlich nahe und obwohl ich mich beim Footprint des kleinen Lautsprechers an das Datenblatt gehalten habe, scheinen die Pins nicht ganz auf die Pads zu passen. Beim Bestücken sollte man jedoch darauf achten, den Taster vor dem Piepser aufzulöten und den Batteriehalter als allerletztes einzulöten. Zum einen, weil sonst die Lötspitze zu stinken anfängt, zum anderen, weil Piepser und Batteriehalter die klobigsten Komponenten sind und sie dadurch das Löten der anderen Bauteile deutlich erschweren. {{Infobox AVR | Typ = ATtiny44 | Takt = 1 | FuseH = DE | FuseL = E2 }} Zum Flashen muss ein Flachbandkabel an den Konnektor, mit nicht eingelegter Batterie können Fuses und Flash geschrieben werden, zumindest wenn man die passende Hexfile hat. Auf Github liegt sie zumindest nicht, also den Compiler selbst anwerfen. <gallery> Datei:Chirp_asm_top.jpg|Von oben... Datei:Chirp_asm_bot.jpg|...und unten </gallery> = Bedienung = Kurz nachdem die Firmware auf dem Controller gelandet ist, fängt das Teil auch an zu Zirpen. Was ich nicht wusste: wenn nichts im EEPROM steht, wird über die LED auch gleich die Referenzhelligkeit gemessen und abgelegt. Später wird erst ab diesem Wert gezirpt. Grundlegend keine schlechte Idee, nur war zu diesem Zeitpunkt die Schreibtischleuchte perfekt auf die LED ausgerichtet. Im etwas dunkleren Wohnzimmer wurde dann geblinkt statt gezirpt. Also die gerade abgeknipste Leitung wieder anlöten, und den EEPROM löschen. So viel vom ersten Fallstrick bei der Bedienung. Ansonsten ist das Teil einfach zu bedienen: Nach dem ersten Einschalten oder dem Drücken des (Re-)Set-Tasters wird die "Trocken-Feuchtigkeit" gemessen, also jene wenn man die Pflanze gießen sollte. Die Messung wird nach ca. 5 Sekunden mit einem längeren Zirpen quittiert. Anschließend kann man die Pflanze (aber nicht den Chirp) mit Wasser versorgen. Die Elektronik wacht immer wieder auf und misst die Kapazität der Sensorfläche. Wird eine zu niedrige Feuchtigkeit ermittelt, legt bei Helligkeit die zirpende Grille los (nein, nicht [https://www.youtube.com/results?search_query=zirpende+Grille+MIB die]). Bei Dunkelheit wird man durch die LED benachrichtigt. Erkennt der Mikrocontroller, dass die Feuchtigkeit gestiegen ist, wird das Gießen wiederum mit einem länglichen Zirpen bestätigt. Nachdem die erste Woche bei meinen widerstandsfähigeren Topfpflanzen (die für den ersten Test herhalten mussten) vorbei war, wurde ich etwas ungeduldig. Kein Zirpen. Einen Tag später legte sie aber los. Nicht zu laut aber dennoch gut hörbar. Bis jetzt sehr zuverlässig. = Lizenz = Das Originalprojekt ist unter der CERN OHL 1.1 lizenziert. Der Einfachheit halber ziehe ich gleich. = Download = * [[Datei:Chirp.zip|Chirp.zip]] = Wer will? = Es gibt noch ein paar der Leiterkarten. Wer eine will, kann sie gerne kostenlos aber gegen Versandkosten haben. Und nein: ich verkaufe keine fertig bestückten Chirps. Vielleicht übernimmt ja Mic mein Layout und bietet es auf Tindie an!? [[Category:AVR]] 77738113864d806905a0b49e71417ba0a667cbd5 Hobbyelektronik.org:Impressum 4 4 1045 896 2016-08-06T20:35:20Z Chris 2 wikitext text/x-wiki == Hauptverantwortlicher == [[Benutzer:Chris|Christof Rueß B.Eng.]]<br/> St.-Wendelin-Str. 9<br>89264 Weißenhorn<br/> E-Mail: chris at hobbyelektronik punkt org<br/> Verschlüsselt: chris-crypt at hobbyelektronik punkt org, [http://hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen)<br/> == Kontakt == Wenn du Fragen an uns hast, lies bitte zuerst nochmal die Seite, zu der du die Frage hast und dann evtl. nochmal die [[FAQ]].<br>Am einfachsten und am unkompliziertesten ist der Kontakt per E-Mail.<br>Um Spams ein bisschen einzuschränken, dürftest du auf der Homepage hier keine klickbaren Links finden. Wie man an die Adresse kommt, muss (so denke ich) nicht erklärt werden. Bitte beachte auch die Seite [[Hobbyelektronik.org:Über Hobbyelektronik.org|Über Hobbyelektronik.org]], auf der insbesondere der Haftungsausschluss zu beachten ist! 02d58e89d9e47442bdd9f363775850f0ed8f2af3 1046 1045 2016-08-06T21:15:44Z Chris 2 vollständig überarbeitet. wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß St.-Wendelin-Str. 9 89264 Weißenhorn ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [http://hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp. Sollte E-Mail zur Kommunikation nicht ausreichen, kann darüber auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch, Abstand davon zu nehmen. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - Attribution-NonCommerial-ShareAlike 3.0 (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies richten auf Ihrem Rechner keinen Schaden an und enthalten keine Viren. Cookies dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * Browsertyp/ Browserversion * verwendetes Betriebssystem * Referrer URL * Hostname des zugreifenden Rechners, IP in gekürzter Form * Uhrzeit der Serveranfrage Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Quelle e-recht24.de (angepasst) 1da566e22e6f0613ca6d06e0f693d58383a8bf26 1047 1046 2016-08-06T21:17:40Z Chris 2 wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [http://hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - Attribution-NonCommerial-ShareAlike 3.0 (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies richten auf Ihrem Rechner keinen Schaden an und enthalten keine Viren. Cookies dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * Browsertyp/ Browserversion * verwendetes Betriebssystem * Referrer URL * Hostname des zugreifenden Rechners, IP in gekürzter Form * Uhrzeit der Serveranfrage Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Quelle e-recht24.de (angepasst) 133d873643d69e3744ba0c3f505b964a48b3efd5 1050 1047 2016-08-25T19:44:59Z Chris 2 Winweis zu Werbung wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [http://hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - Attribution-NonCommerial-ShareAlike 3.0 (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies richten auf Ihrem Rechner keinen Schaden an und enthalten keine Viren. Cookies dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * Browsertyp/ Browserversion * verwendetes Betriebssystem * Referrer URL * Hostname des zugreifenden Rechners, IP in gekürzter Form * Uhrzeit der Serveranfrage Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Quelle e-recht24.de (angepasst) =Werbung= Was vielen auf dieser Homepage dank AdBlock wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, dann muss das zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jeder, der diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' b229d08a89c99e4718f997f3ef7bfd1cf249ea9b 1052 1050 2016-08-27T22:14:50Z Chris 2 link auf PK agnostisch gemacht wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - Attribution-NonCommerial-ShareAlike 3.0 (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies richten auf Ihrem Rechner keinen Schaden an und enthalten keine Viren. Cookies dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * Browsertyp/ Browserversion * verwendetes Betriebssystem * Referrer URL * Hostname des zugreifenden Rechners, IP in gekürzter Form * Uhrzeit der Serveranfrage Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Quelle e-recht24.de (angepasst) =Werbung= Was vielen auf dieser Homepage dank AdBlock wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, dann muss das zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jeder, der diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' f6f53d15073b5d96f845a7c9dfaad2bcc13b261e Reparatur iTP A3 EOS 0 385 1048 945 2016-08-06T21:28:52Z Qsysopr 1 /* Reparatur */ Bild hinzugefügt wikitext text/x-wiki [[Datei:iTP_Gesamt.jpg|thumb|iTP A3 EOS im Vergleich zu einer AA-Zelle]] Vor ein paar Jahren habe ich mir eine iTP A3 EOS (upgraded) zugelegt. Wem die Bezeichnung nichts sagt: keine Sorge, muss man nicht kennen - es handelt sich dabei um eine Taschenlampe. Sie hat bis zu 96 Lumen (in 3 Stufen), obwohl sie nicht besonders größer als eine AA-Batterie ist (14 mm Durchmesser, 67 mm lang). Versorgt wird sie durch eine einzelne AAA-Zelle wobei der eingebaute Schaltwandler bis knapp 0,9 Volt läuft. Er holt also fast alles aus der Zelle, auch wenn die Taschenlampe zum Ende hin etwas dunkler wird. Das Teil ist - wie so vieles - toll, solange es funktioniert. Nachdem das Lämpchen immer am Schlüsselbund ist und dementsprechend öfter mal runter fiel, war nach knapp drei Jahren Schluss. Erst ging sie erst nach zudrehen und anschnippen an, später musste man etwas klopfen, dann blieb sie dauerhaft aus. Grmpf. Wegwerfen? Auf keinen Fall! Zumal es sie anscheinend nicht mehr zu Kaufen gibt. = Auf das Ding! = Das wahrscheinlich schwierigste Unterfangen an der Reparatur - Der Kopf der Lampe ist schnell drunten, aber wie kommt man an die Elektronik? Zwei Löcher in der Leiterkarte und das Gewinde verraten den Trick: Rausschrauben. Dazu nimmt man am besten eine ältere und sehr stabile Pinzette oder spannt zwei passende Stahlstifte (am besten mit Absatz oder konisch, damit man innen nichts aufspießt) in einen Schraubstock. <gallery> Datei:iTP_Kopf.jpg|Taschenlampenkopf von hinten Datei:iTP_oeffnen.jpg|Einrasten & Drehen </gallery> Erschwerend kommt dazu, dass der Innenkörper mit dem Lampenkopf verklebt wurde. Dagegen arbeitet man am besten mit Wärme und sanfter Gewalt. Es hilft auch, den Innenkörper immer wieder ein Stück hineinzudrehen. Hat man das Innenleben befreit, ist es empfehlenswert, die Klebereste vollständig zu entfernen - sowohl am Innenteil als auch am Lampenkopf. Sonst wird das Einschrauben später noch schwieriger. Dazu am Besten wieder erwärmen und vorsichtig (das Alu ist relativ weich) die Gewindegänge auskratzen. <gallery> Datei:iTP_Innenkoerper_oben.jpg|Helle Seite... Datei:iTP_Innenkoerper_unten.jpg|...und dunkle Seite des Innenkörpers </gallery> Um an die Elektronik zu kommen, muss zunächst die Leiterkarte runter, die zugleich den Kontakt zur Batterie darstellt. Dazu geht man am besten mit einem feinen Schraubendreher in die Nut und hebelt sie vorsichtig heraus. Wärme hilft auch hier gegen den Kleber. Oft sieht man nach diesem Schritt schon den Defekt: <gallery> Datei:iTP_Leitungsbruch1.jpg Datei:iTP_Leitungsbruch2.jpg Datei:iTP_Leitungsbruch3.jpg </gallery> Leitungsbruch. = Reparatur = Damit das Löten einfacher vonstatten geht (es ist verdammt eng!) habe ich bei meinen beiden Reparaturen auch die LED herausgenommen. Dazu muss man auf der anderen Seite des Innenteils zuerst die Plastikabdeckung herausnehmen und anschließend die Anschlussdrähte ablöten. <gallery> Datei:iTP_LED1.jpg|Mit Deckel Datei:iTP_LED2.jpg|Ohne Deckel Datei:ITP Waermeleitpaste.jpg|Ohne LED aber mit Pampe Datei:iTP_LED3.jpg|Ohne LED und Pampe </gallery> Da die Wärmeleitpaste eh eingetrocknet ist, kann man sie auch gleich entfernen/erneuern. Isopropanol und Wattestäbchen sind hier die Mittel der Wahl. Wenn man das Teil schon einmal offen hat: Am besten beide Leitungen zum Batteriekontakt tauschen! Ich habe bei der ersten Reparatur vor einem halben Jahr den Fehler gemacht, nur die gebrochene Leitung neu anzulöten und durfte das Teil jetzt noch einmal öffnen. Die beiden Litzen sind recht kurz zu halten, 1 cm ist mehr als genug. Auf jeden Fall sollte man eine feine Litze nehmen (meine ist schon fast zu dick), damit die Lötstellen nicht wieder so schnell brechen. = Zusammenbau = Und schon liegt das Teil wieder da wie eine aufgebrachte Krabbe - bis man es wieder in die Behausung steckt: <gallery> Datei:iTP_Zusammenbau1.jpg|[http://www.youtube.com/results?search_query=findet+nemo+krabben+hey Hey!] Datei:iTP_Zusammenbau2.jpg|Zusammengeklappt Datei:iTP_Zusammenbau3.jpg|und wieder eingebaut </gallery> Wichtig beim Zusammenbau: die Drähte für die LED durch die Löcher stecken und dann die Elektronik um 180 Grad drehen, sonst schauen die Drähte viel zu weit heraus. (Alternativ: zuerst LED anlöten und dann die Elektronik ins Alugehäuse einsetzen) Die vorher entfernte Wärmeleitpaste durch neue ersetzt (wie beim PC gilt: weniger ist manchmal mehr und bei mir ist es fast schon zu viel) und schon kann man die LED wieder anlöten. Beim Anlöten der Drähte an die LED müssen diese gegen den Uhrzeigersinn liegen (siehe oben), sonst passt die Plastikkappe nicht! Bei der LED sind übrigens sowohl Anode als auch Kathode auf der Trägerplatine markiert (+ und -) Die Kontaktplatine wieder eingedrückt (wenn sie fest hält, muss man sie nicht einmal verkleben) kann das Modul wieder ins Gehäuse. Und sie leuchtet wieder! [[Kategorie:Elektronik]] [[Kategorie:Reparatur]] b220945654a0babe5bf19858fc8384969a44c2a2 Hauptseite 0 1 1049 1043 2016-08-25T19:18:22Z Chris 2 Links zum Blog (hoffentlich) SSL-tauglich gemacht wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *23.06.2016 [[Minichirp]] *02.01.2016 [[Lichtsensor Avago APDS-9300]] *01.04.2015 [[Mini-Schaltwandler]] *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] ==Änderungen== *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *15.06.2015 Ein durchgebranntes [[Netzfilter]] und seine Reparatur *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. 9fb3a78f4b857243dacb23c96dcf5648f82e5fd6 1051 1049 2016-08-27T22:09:57Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *23.06.2016 [[Minichirp]] *02.01.2016 [[Lichtsensor Avago APDS-9300]] *01.04.2015 [[Mini-Schaltwandler]] *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] *10.05.2014 [[Kühlung für Zhongdi ZD-939L]] ==Änderungen== *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. d2ebae621ed61765e8f315fee5a1eb95386b8aa1 1067 1051 2016-12-31T17:45:27Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <latestblogposts /> ==Neues== *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *23.06.2016 [[Minichirp]] *02.01.2016 [[Lichtsensor Avago APDS-9300]] *01.04.2015 [[Mini-Schaltwandler]] *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] ==Änderungen== *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. 50f95cf4695c5389b105808e8dd949df1f49891a 1089 1067 2017-02-25T11:48:08Z Chris 2 latestposts -> WPPlatest wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *23.06.2016 [[Minichirp]] *02.01.2016 [[Lichtsensor Avago APDS-9300]] *01.04.2015 [[Mini-Schaltwandler]] *19.11.2014 [[Stellaris Launchpad-Toolchain unter Linux]] *24.08.2014 [[Reparatur iTP A3 EOS]] ==Änderungen== *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. 77bd398a3ff1ab90597011bdd7332a1cee25910f Energieerfassung 0 168 1053 711 2016-09-29T08:24:35Z Chris 2 Typo korrigiert wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== [[Datei:Nrg hauptzaehler.jpg|thumb|Stromzähler mit aufgesetzter Erfassungseinheit]] Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[:wpde:Ferraris-Zähler|Ferraris-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. [[Datei:Bananen Frucht.jpg|thumb|Eine Banane, eisenreich und sehr bekömmlich (cc:by-sa Darkone)]] Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. <gallery> Datei:Nrg zaehler umlauf.png|Ein Umlauf, wie er direkt am Fototransistor gemessen wird Datei:Nrg zaehler rauschen.png|"Grundrauschen" der rotierenden Scheibe (ohne DC-Offset) </gallery> Die Leistungsaufnahme lässt sich anhand der Umlaufzeit wie folgt berechnen: <math> P=\frac{1}{t}\frac{\textrm{rot}}{\textrm{s}}\cdot \frac{1}{75}\frac{\textrm{kWh}}{\textrm{rot}}\cdot 3600 \frac{\textrm{W}}{\textrm{h}}\cdot 1000\frac{\textrm{W}}{\textrm{kW}} = \frac{1}{t}\frac{\textrm{1}}{\textrm{s}}\cdot \frac{3600\cdot 1000}{75}\textrm{Ws} = \frac{1}{t}\frac{\textrm{1}}{\textrm{s}}\cdot 48000\textrm{Ws} </math> Setzt man die im Screenshot ermittelten 42.6 Sekunden ein, erhält man eine Leistung von ~1127 Watt. Da die Leistung mit der Zeit exponentiell abnimmt, ist bei hohen Leistungsaufnahmen eine relativ hohe Auflösung der Zeit erforderlich. Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: <gallery> Datei:Nrg zaehler auswert.png|Auswerteschaltung Datei:Nrg zaehler pass.png|Zählersignal vor (blau) und nach (gelb) dem Filter </gallery> Links wird der Fototransistor in Sperrrichtung angeschlossen. Der 1µF-Elko und der nachfolgende 100k-Widerstand stellt einen Hochpass mit nicht näher definierter Grenzfrequenz (WolframAlpha sagt [http://www.wolframalpha.com/input/?i=1%2F%282*Pi*100kOhms*1%C2%B5F%29 1.592Hz]) dar. Die Frequenz ist ist im Hinblick auf [[:wpde:Hochpass:Ordnung]], Bauteiletoleranzen und der Zielfrequenz vermutlich nicht einmal ein Richtwert. Der folgende Hochpass hat eine Grenzfrequenz von ca. 16Hz. Hier gilt das gleiche Vertrauen wie in den Tiefpass. Aber alles kein Problem: Die Werte sind weitestgehend unkritisch. Es sind Umläufe im Millihertz-Bereich (also Umlaufdauern in der Größenordnung Sekunden bis Minuten) zu erwarten. Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. [[Datei:Nrg tarifzaehler.jpg|thumb|Tarifzähler, rechts das Fähnchen zum Anzeigen des Tarifs]] Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. [[Datei:Nrg_relais_freigabe.jpg|thumb|Relais für die Stromfreigabe, mit LED]] Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. '''Update 10.10.2010:''' Weasel (IRC) ist beim Anblick der Kennlinie der Temperatursensoren in der Anleitung des Vitosolic 200 blitzschnell darauf gekommen, dass es sich um PT500-Elemente handeln müssen, die jedoch nur für sehr teuer Geld erhältlich sind. Mein anfänglicher Scherz vonwegen 2 PT1000 parallel ergibt PT500 hat sich als gar nicht so dumm erwiesen: Idealerweise sind die Widerstände der Sensoren bei gleicher Temperatur ebenfalls gleich, Durch Parallelschaltung zweier PT1000 kann man sie problemlos an der PT1000 betreiben! Da ich sonst nichts mit meinen 9 Sensoren anzufangen wusste, fristen jetzt 8 dieser als 4 Fühler im Keller ihr dasein: Zwei erfassen die Ein- und Auslasstemperatur an der "Primärseite" der Wärmepumpe, einer sitzt im Warmwasserspeicher in oberster Schicht und der 4. misst (da mir noch nichts besseres einfiel) die Raumtemperatur im Heizkeller, die mangels Isolierung der Rohre deutlich zu hoch ist. '''Update-Ende''' === Was kommt rein? === Auf der Unterseite [[Energieerfassung/Solarleistung]] habe ich beschrieben, wie man anhand einiger Parameter die Leistung der Solaranlage berechnen kann ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. <gallery> Datei:Nrg shield.jpg|Shield des Großhirns Datei:Nrg grosshirn.jpg|Hirn von oben </gallery> ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://www.jump.to/fleury Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. <gallery> Datei:Nrg lcd 1.jpg|Home-Screen mit Datum und Uhrzeit Datei:Nrg lcd 2.jpg|Aktueller Stromverbrauch Datei:Nrg lcd 3.jpg|Solardaten: Kollektortemperatur, Pumpenlast und Speichertemp. Datei:Nrg lcd 4.jpg|Debuginfos, Timeouts des TCP/IP-Stacks und Refresh des NTP-Clients </gallery> ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== [[Datei:Nrg json.png|thumb|Exemplarischer JSON-Datensatz]] Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= Aktuelle Firmware, EAGLE-Dateien des Shields (ohne V-Bus-Pegelwandler): [[Datei:Energieerfassung Firmware.zip]] =Nerviges/Todo= *Die interne Uhr hat eine sehr hohe Gangabweichung. Macht sich trotz kurzer NTP-Refresh-Intervallen bemerkbar *Der Speicher für die historischen Daten ist sehr klein. Bei Ausfall der Internetverbindung/Server/Cronjob gibt es zu schnell Lücken *Erfassung des Wasserzählers *Erfassung Außentemperatur =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Pads der LEDs zu groß und Widerstände gegen GND geschaltet) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann *[http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller *Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] 0444813a10cc9c0a301cf9b92112682a88744ca2 Datei:Briefkasten led.jpg 6 439 1054 2016-12-31T17:09:56Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Briefkasten sch1.png 6 440 1055 2016-12-31T17:10:14Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Briefkasten sch2.png 6 441 1056 2016-12-31T17:10:21Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Briefkasten sensor.jpg 6 442 1057 2016-12-31T17:10:33Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Einfacher LED-Treiber.png 6 443 1058 2016-12-31T17:10:42Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Briefkasten.zip 6 444 1059 2016-12-31T17:14:57Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Briefkasteninnenbeleuchtung 0 445 1060 2016-12-31T17:24:27Z Chris 2 Seite erstellt wikitext text/x-wiki Zugegeben, es hört sich nicht nur bescheuert an, es ist auch so. Trotzdem hatte ich das Bedürfnis, eine Briefkasteninnenbeleuchtung zu bauen. Warum? Nein, nicht (nur) weil ich es kann, sondern weil sie durchaus praktisch ist = Problemstellung = Die Briefkästen vom Mietshaus hier sind freistehend und in der dunklen Jahreszeit sieht man durch aufgrund der etwas ungünstig installierten Außenbeleuchtung den Einwurf nicht, ob Post gekommen ist. Durch das Öffnen der Frontklappe sieht und bekommt man zwar den Inhalt, aber dazu bin ich schlicht zu faul. Umbauten müssen rückstandsfrei sein, schließlich will ichs nicht mit meinen Vermietern verscherzen. = Idee = In den Briefkasten soll mindestens eine LED, die durch das Öffnen des Deckels aktiviert wird. Die Befestigung findet über Magnete statt, die Stromversorgung durch Batterien. Damit diese nicht unnötig leergesaugt werden, soll die Beleuchtung zeitlich begrenzt sein. = Umsetzung = Zumindest bei der LED ist die Sache schnell klar: weiße PLCC2 liegen hier mehr als genug herum. Um sie sinnvoll zu betreiben, kommen 3 Mignon-Batterien in Serie zum Einsatz. Bei 3,3 Volt (also wenn die Zellen schon halb-platt sind) sind 7 mA mehr als genug, der passende Widerstand hierfür wäre 171 Ohm. Wäre, weil ein einfacher Vorwiderstand an dieser Stelle dumm ist - die Batteriespannung wird mit dem Ladestand fallen - und damit der Strom durch die LED. == LED-Treiber == Besser ist es deshalb, eine Konstantstromquelle zu verwenden. Die lässt sich sehr einfach aufbauen, zwei Transistoren und zwei Widerstände reichen. Der Strom wird über den unteren Widerstand und Transistor definiert: letzterer wird leitend, wenn seine Basis-Emitter-Spannung über ca. 0,7 Volt steigt - diese Spannung muss beim gewünschten Strom eingeprägt werden. Für den Widerstand gilt also: <math>\textrm{R}=\frac{0.7}{\textrm{I}_\textrm{out}}</math> Der obere Transistor steuert den Strom durch die LED. Der Widerstand dient lediglich als Pull-up und ist daher eher unkritisch. Wer ihn hinreichend groß Dimensionierung will, muss sich den LED-Strom und den Verstärkungsfaktor ansehen. Die mechanische Integration ist einfach: ich habe noch kleine Leiterkärtchen, eigentlich für einen anderen Zweck, aber es passt alles für diese Schaltung drauf. Schrumpfschlauch drüber, kleine Magnete ran, nochmal Schrumpfschlauch. Bild von den Innereien gibt es leider keine. == Schalter == Für die Erkennung ob der Deckel offen ist gibt es viele Möglichkeiten: mechanischer Taster, Näherungssensoren, Neigungsschalter, Hallswitches, etc.. Ich habe mich bewusst für einen Reed-Kontakt entschieden - mechanische Schalter brauchen in aller Regel viel Kraft (und viel Gegenkraft kann ich bei der Montage nicht bieten) und sind oft empfindlich auf Feuchte. Viele Näherungssensoren (optisch, kapazitiv und induktiv) sind aktiv und haben einen relativ großen Ruhestrom. Nichts für langen Batteriebetrieb. Neigungsschalter geht, war aber früher dank Quecksilber eine ziemliche Sauerei; die aktuellen sind wahrscheinlich besser aber ich habe Vorbehalte. Schlussendlich habe ich einen Reed-Kontakt verwendet. Hermetisch abgeschlossen, kraftfrei und kein Ruhestrom. Wenn man mechanisch faul ist oder nicht genug Grips in der Birne hat, braucht man einen Öffner - genau das (bzw.einen Wechsler) habe ich bestellt. Um die Integration vorweg zu nehmen: der Kontakt ist auf einer kleinen länglichen Leiterkarte gelandet - lang genug, um einen Magnet zur Montage am Briefkasten verwenden zu können. Jetzt kommt auch die Sache mit dem Grips: Der "Montagemagnet" war stark genug, damit das durch das Metall laufende Feld den Kontakt öffnete. Mit geschickter Positionierung beider Magnete (der zur Montage und dem im Deckel) hätte ich die Felder so ausrichten können, dass sie sich im Deckel-zu-Fall neutralisiert hätten. Hätte-hätte... Aber auch so funktioniert es. Um vor Feuchtigkeit besser geschützt zu sein, kommt alles in Schrumpfschlauch und wird natürlich auf der etwas besser geschützten Seite des Briefkastens installiert. Foddo == Abschaltautomatik == {{Infobox AVR | Typ = ATtiny45 | Takt = 0,6 | FuseH = FF | FuseL = 61 }} Eigentlich wäre diese prädestiniert für eine Analogschaltung oder einen NE555. Schlussendlich wurde es aber ein ATtiny13. Der ist mit der Aufgabe zwar gänzlich unterfordert, braucht dafür im Schlaf nahezu keinen Strom und zudem fast keine Außenbeschaltung Das Programm könnte sehr einfach sein: Port initialisieren, Pin an, warten, Pin aus. Mit 4,8 MHz Takt braucht der Controller einige Milliampere, was in beiderlei Hinsicht unnötig viel ist. Über die CLKDIV-Fuse kann der Takt auf ein Achtel reduziert werden - besser aber trotzdem nicht überragend. Was ich beim Programmieren übersehen habe: den Watchdog als Taktquelle - 128 kHz und noch etwas stromsparender. Im [http://www.atmel.com/images/doc2535.pdf Datenblatt] kann man sich dazu Figure 19-1 und 19-5 anschauen. Demnach braucht der Chip bei 600 kHz (bei externer Taktquelle) zwischen 0,3 und 0,5 mA - mit dem Watchdog wären es lediglich 0,06 bis 0,09 mA. Statt warten per Delay kann man auch den internen Timer verwenden und die CPU bei Overflow wecken. Nur leider kann man mit weiterlaufendem Takt den Tiny nicht tief genug schlafen schicken, damit es richtig gut wird. Geht man in den Tiefschlaf, bleibt der Takt komplett weg und das war dann für den Timer. Glücklicherweise kann man den Watchdog so konfigurieren, dass er keinen Reset sondern einen Interrupt auslöst. Da er einen eigenen Oszillator hat, ist er zudem unabhängig vom Systemtakt. Sein Vorteiler lässt sich bis in den angenehmen Sekundenbereich einstellen. Im Power-Down und aktivem Watchdog braucht der Prozessor (Figure 19-14) zwischen 4,5 und 7,0 µA. Nachdem das Programm durch ist und sich der Bursche schlafen legt, sinkt der Stromverbrauch (Figure 19-13) auf sehr niedrige 0,2 bis 1,2 µA. Wo liegt nochmal die Selbstentladung von Alkali-Zellen? == Batteriewächter == Darf's ein bisschen mehr sein? Der ATtiny13 hat einen ADC, warum also nicht noch zusätzlich eine Warnung für bald leere Batterien einbauen? Einige AVRs können den ADC verkehrte Welt spielen lassen: Man kann die interne Referenz als Eingang wählen und die Versorgungsspannung als Referenz. Dadurch wird das Ergebnis zwar reziprok aber die Messung braucht keine externe Beschaltung und ist zudem sehr stromsparend. Geht hier leider nicht (Figure 14-1). Es muss also ein externer Spannungsteiler her. Der braucht permanent einen gewissen Strom und das ist Mist. Man kann die Widerstände zwar nach oben dimensionieren, dann wird die Messung durch ADC-bedingte Verfälschungen ungenauer. Ich bin einen etwas faulen (im Sinne von: warum mehr Zeit verschwenden) Kompromiss eingegangen: Der Spannungsteiler wird vom Schaltsignal für die LEDs versorgt. Dadurch haut der Strom nur für die maximal 30 Sekunden ab und zugleich hat der FET einen Pull-Dowm am Gate, falls der IO doch mal floatet. Der Treiber im AVR ist einen leichten Spannungsabfall haben, aber zum einen kann man kalibrieren und zum anderen wird keine besonders hohe Genauigkeit benötigt. Bei der Dimensionierung muss man - wie bereits erwähnt - darauf achten, dass die Messung halbwegs sauber funktioniert aber gleichzeitig nicht unnötig viel Strom verbraucht wird. Natürlich muss auch der Teiler passen. Für diesen Zweck verwende ich gerne [Widerstand ist zwecklos https://www.muellerzumhagen.de/widerstand-ist-zwecklos-pointless-resistance/], das die Paarung 33 kOhm (top) und 10 kOhm (bottom) ausspuckte. Damit ergibt sich eine maximal messbare Spannung von 4,73 V und ein Stromverbrauch von nicht ganz 105 µA bei 4,5 V. Die Auflösung wäre damit nicht ganz 4,6 mV - deutlich mehr als genug. Der ADC-Wert berechnet sich theoretisch wie folgt: <math>\textrm{ADC}= \textrm{U}_{\textrm{bat}} \cdot \frac{10\textrm{ k}\Omega}{10\textrm{ k}\Omega+33\textrm{ k}\Omega} \cdot \frac{1024}{1.1\textrm{ V}}</math> Die Messung selbst ist geradeaus: Auswählen der Referenz und Eingang (PB4), Takt festlegen, Interrupt an und los geht's. Um etwas sinnvolles zu machen während die Messung durchgeführt wird, legt sich der Kern schlafen und wird wieder geweckt, sobald diese durch ist (sei(); nicht vergessen!). Anschließend wird der ADC-Wert ausgelesen und der Block wieder deaktiviert. Um etwas bessere Ergebnisse zu erlangen, wird die Batteriespannung nicht direkt nach dem Start sondern nach einer Sekunde durchgeführt. Dadurch lassen sich zwei Dinge verknüpfen: Die Batterien sehen eine Last und man ist am richtigen Zeitpunkt, um die LEDs kurz auszuschalten. === Kalibrierung === Aufgrund der Beschaltung sah ich mich genötigt, den ADC zu testen. Der einfachste Weg dafür wäre UART, den es aber nicht gibt. Zumindest nicht in Hardware. Das Format ist relativ einfach, siehe [[wpde:Universal_Asynchronous_Receiver_Transmitter|Wikipedia]]. Idle high, Startbit, Daten und ein bisschen Pause fürs Stopbit (die ich mir gespart hab). Mit dem Wissen, wie lange ein NOP in der CPU dauert die Timings angepasst und los geht's. Mit "normalen" USB<>UART-Adaptern hat man allerdings wenig Spaß: meine Implementierung verwendet - der Faulheit wegen - 10 Datenbits und eine ziemlich krumme Baudrate, die halt einfach gerade gepasst hat. Der Logic Analyzer kann das, die meisten Wandler aber nicht. Aber wer will schon Interoperabilität? Das Ende vom Lied: die Berechnung von oben ist hinreichend genau. == Einbau == = Es geht besser! = Kein Projekt würde mal zweimal genau gleich machen. So auch hier. Ich würde die LED-Treiber mit FET statt Bipolar-Transistoren bauen und dann auch gleich den gemeinsamen FET zum Schalten der Treiber sparen, indem die Versorgung von den Transistoren direkt vom Mikrocontroller kommt. Den Spannungsteiler würde ich eine Nummer größer dimensionieren und etwas mehr Ungenauigkeit (who cares?!) in Kauf nehmen. Genauso würde ich im AVR gleich den Watchdog als Taktquelle nehmen. Läuft ja eh. Beim Reedkontakt würde ich wahrscheinlich einen Schließer nehmen, ihn durch den Befestigungsmagnet "vorspannen" und das Feld durch den Magnet im Deckel neutralisieren. Geht sicher auch auf länger gut und senkt die Bauteilkosten. Genauso würde ich die Betriebsdauer wahrscheinlich auf 10 Sekunden verringern. Wer starrt schon 30 Sekunden in einen Briefkastenschlitz? Um die Schaltung etwas zu verbessern, kann man den oberen NPN-Transistor durch einen n-Kanal-FET ersetzen und den Pull-up größer dimensionieren. Spart zumindest ein bisschen Strom. c2ab129b8c736a091911a3673d8f3f6a37beea9c 1061 1060 2016-12-31T17:36:30Z Chris 2 Danke Mediawiki, dass du meine Änderungen verworfen hast :( wikitext text/x-wiki Zugegeben, es hört sich nicht nur bescheuert an, es ist auch so. Trotzdem hatte ich das Bedürfnis, eine Briefkasteninnenbeleuchtung zu bauen. Warum? Nein, nicht (nur) weil ich es kann, sondern weil sie durchaus praktisch ist = Problemstellung = Die Briefkästen vom Mietshaus hier sind freistehend und in der dunklen Jahreszeit sieht man durch aufgrund der etwas ungünstig installierten Außenbeleuchtung den Einwurf nicht, ob Post gekommen ist. Durch das Öffnen der Frontklappe sieht und bekommt man zwar den Inhalt, aber dazu bin ich schlicht zu faul. Umbauten müssen rückstandsfrei sein, schließlich will ichs nicht mit meinen Vermietern verscherzen. = Idee = In den Briefkasten soll mindestens eine LED, die durch das Öffnen des Deckels aktiviert wird. Die Befestigung findet über Magnete statt, die Stromversorgung durch Batterien. Damit diese nicht unnötig leergesaugt werden, soll die Beleuchtung zeitlich begrenzt sein. = Umsetzung = Zumindest bei der LED ist die Sache schnell klar: weiße PLCC2 liegen hier mehr als genug herum. Um sie sinnvoll zu betreiben, kommen 3 Mignon-Batterien in Serie zum Einsatz. Bei 3,3 Volt (also wenn die Zellen schon halb-platt sind) sind 7 mA mehr als genug, der passende Widerstand hierfür wäre 171 Ohm. Wäre, weil ein einfacher Vorwiderstand an dieser Stelle dumm ist - die Batteriespannung wird mit dem Ladestand fallen - und damit der Strom durch die LED. == LED-Treiber == Besser ist es deshalb, eine Konstantstromquelle zu verwenden. Die lässt sich sehr einfach aufbauen, zwei Transistoren und zwei Widerstände reichen. Der Strom wird über den unteren Widerstand und Transistor definiert: letzterer wird leitend, wenn seine Basis-Emitter-Spannung über ca. 0,7 Volt steigt - diese Spannung muss beim gewünschten Strom eingeprägt werden. Für den Widerstand gilt also: :<math>\textrm{R}=\frac{0.7}{\textrm{I}_\textrm{out}}</math> Der obere Transistor steuert den Strom durch die LED. Der Widerstand dient lediglich als Pull-up und ist daher eher unkritisch. Wer ihn hinreichend groß Dimensionierung will, muss sich den LED-Strom und den Verstärkungsfaktor ansehen. Die mechanische Integration ist einfach: ich habe noch kleine Leiterkärtchen, eigentlich für einen anderen Zweck, aber es passt alles für diese Schaltung drauf. Schrumpfschlauch drüber, kleine Magnete ran, nochmal Schrumpfschlauch. <gallery> Datei:Einfacher_LED-Treiber.png|Schaltplan des einfachen LED-Treibers Datei:Briefkasten_led.jpg|Aufgebauter LED-Triber mit LED, Magnet und Schrumpfschlauch </gallery> Bild von den Innereien gibt es leider keine. == Schalter == Für die Erkennung ob der Deckel offen ist gibt es viele Möglichkeiten: mechanischer Taster, Näherungssensoren, Neigungsschalter, Hallswitches, etc.. Mechanische Schalter brauchen in aller Regel viel Kraft (und viel Gegenkraft kann ich bei der Montage nicht bieten) und sind oft empfindlich auf Feuchte. Viele Näherungssensoren (optisch, kapazitiv und induktiv) sind aktiv und haben einen relativ großen Ruhestrom. Nichts für langen Batteriebetrieb. Neigungsschalter geht, war aber früher dank Quecksilber eine ziemliche Sauerei; die aktuellen sind wahrscheinlich besser aber ich habe Vorbehalte. Schlussendlich habe ich einen Reed-Kontakt verwendet. Hermetisch abgeschlossen, kraftfrei und kein Ruhestrom. Wenn man mechanisch faul ist oder nicht genug Grips in der Birne hat, braucht man einen Öffner - genau das (bzw. einen Wechsler) habe ich bestellt. Um die Integration vorweg zu nehmen: der Kontakt ist auf einer kleinen länglichen Leiterkarte gelandet - lang genug, um einen Magnet zur Montage am Briefkasten verwenden zu können. Jetzt kommt auch die Sache mit dem Grips: Der "Montagemagnet" war stark genug, damit das durch das Metall laufende Feld den Kontakt öffnete. Mit geschickter Positionierung beider Magnete (der zur Montage und dem im Deckel) hätte ich die Felder so ausrichten können, dass sie sich im Deckel-zu-Fall neutralisiert hätten. Hätte-hätte... Aber auch so funktioniert es. Um vor Feuchtigkeit besser geschützt zu sein, kommt alles in Schrumpfschlauch und wird natürlich auf der etwas besser geschützten Seite des Briefkastens installiert. <gallery> Datei:Briefkasten_sensor.jpg|unten: Reedschalter auf Leiterkarte mit Magnet, oben (überbelichtet): Magnet </gallery> == Abschaltautomatik == {{Infobox AVR | Typ = ATtiny45 | Takt = 0,6 | FuseH = FF | FuseL = 61 }} Eigentlich wäre diese prädestiniert für eine Analogschaltung oder einen NE555. Schlussendlich wurde es aber ein ATtiny13. Der ist mit der Aufgabe zwar gänzlich unterfordert, braucht dafür im Schlaf nahezu keinen Strom und zudem fast keine Außenbeschaltung Das Programm könnte sehr einfach sein: Port initialisieren, Pin an, warten, Pin aus. Mit 4,8 MHz Takt braucht der Controller einige Milliampere, was in beiderlei Hinsicht unnötig viel ist. Über die CLKDIV-Fuse kann der Takt auf ein Achtel reduziert werden - besser aber trotzdem nicht überragend. Was ich beim Programmieren übersehen habe: den Watchdog als Taktquelle - 128 kHz und noch etwas stromsparender. Im [http://www.atmel.com/images/doc2535.pdf Datenblatt] kann man sich dazu Figure 19-1 und 19-5 anschauen. Demnach braucht der Chip bei 600 kHz (bei externer Taktquelle) zwischen 0,3 und 0,5 mA - mit dem Watchdog wären es lediglich 0,06 bis 0,09 mA. Statt warten per Delay kann man auch den internen Timer verwenden und die CPU bei Overflow wecken. Nur leider kann man mit weiterlaufendem Takt den Tiny nicht tief genug schlafen schicken, damit es richtig gut wird. Geht man in den Tiefschlaf, bleibt der Takt komplett weg und das war dann für den Timer. Glücklicherweise kann man den Watchdog so konfigurieren, dass er keinen Reset sondern einen Interrupt auslöst. Da er einen eigenen Oszillator hat, ist er zudem unabhängig vom Systemtakt. Sein Vorteiler lässt sich bis in den angenehmen Sekundenbereich einstellen. Im Power-Down und aktivem Watchdog braucht der Prozessor (Figure 19-14) zwischen 4,5 und 7,0 µA. Nachdem das Programm durch ist und sich der Bursche schlafen legt, sinkt der Stromverbrauch (Figure 19-13) auf sehr niedrige 0,2 bis 1,2 µA. Wo liegt nochmal die Selbstentladung von Alkali-Zellen? == Batteriewächter == Darf's ein bisschen mehr sein? Der ATtiny13 hat einen ADC, warum also nicht noch zusätzlich eine Warnung für bald leere Batterien einbauen? Einige AVRs können den ADC verkehrte Welt spielen lassen: Man kann die interne Referenz als Eingang wählen und die Versorgungsspannung als Referenz. Dadurch wird das Ergebnis zwar reziprok aber die Messung braucht keine externe Beschaltung und ist zudem sehr stromsparend. Geht hier leider nicht (Figure 14-1). Es muss also ein externer Spannungsteiler her. Der braucht permanent einen gewissen Strom und das ist Mist. Man kann die Widerstände zwar nach oben dimensionieren, dann wird die Messung durch ADC-bedingte Verfälschungen ungenauer. Ich bin einen etwas faulen (im Sinne von: warum mehr Zeit verschwenden) Kompromiss eingegangen: Der Spannungsteiler wird vom Schaltsignal für die LEDs versorgt. Dadurch haut der Strom nur für die maximal 30 Sekunden ab und zugleich hat der FET einen Pull-Dowm am Gate, falls der IO doch mal floatet. Der Treiber im AVR ist einen leichten Spannungsabfall haben, aber zum einen kann man kalibrieren und zum anderen wird keine besonders hohe Genauigkeit benötigt. Bei der Dimensionierung muss man - wie bereits erwähnt - darauf achten, dass die Messung halbwegs sauber funktioniert aber gleichzeitig nicht unnötig viel Strom verbraucht wird. Natürlich muss auch der Teiler passen. Für diesen Zweck verwende ich gerne [Widerstand ist zwecklos https://www.muellerzumhagen.de/widerstand-ist-zwecklos-pointless-resistance/], das die Paarung 33 kOhm (top) und 10 kOhm (bottom) ausspuckte. Damit ergibt sich eine maximal messbare Spannung von 4,73 V und ein Stromverbrauch von nicht ganz 105 µA bei 4,5 V. Die Auflösung wäre damit nicht ganz 4,6 mV - deutlich mehr als genug. Der ADC-Wert berechnet sich theoretisch wie folgt: :<math>\textrm{ADC}= \textrm{U}_{\textrm{bat}} \cdot \frac{10\textrm{ k}\Omega}{10\textrm{ k}\Omega+33\textrm{ k}\Omega} \cdot \frac{1024}{1.1\textrm{ V}}</math> Die Messung selbst ist geradeaus: Auswählen der Referenz und Eingang (PB4), Takt festlegen, Interrupt an und los geht's. Um etwas sinnvolles zu machen während die Messung durchgeführt wird, legt sich der Kern schlafen und wird wieder geweckt, sobald diese durch ist (sei(); nicht vergessen!). Anschließend wird der ADC-Wert ausgelesen und der Block wieder deaktiviert. Um etwas bessere Ergebnisse zu erlangen, wird die Batteriespannung nicht direkt nach dem Start sondern nach einer Sekunde durchgeführt. Dadurch lassen sich zwei Dinge verknüpfen: Die Batterien sehen eine Last und man ist am richtigen Zeitpunkt, um die LEDs kurz auszuschalten. <gallery> Datei:Briefkasten_sch1.png|Schaltung </gallery> === Kalibrierung === Aufgrund der Beschaltung sah ich mich genötigt, den ADC zu testen. Der einfachste Weg dafür wäre UART, den es aber nicht gibt. Zumindest nicht in Hardware. Das Format ist relativ einfach, siehe [[wpde:Universal_Asynchronous_Receiver_Transmitter|Wikipedia]]. Idle high, Startbit, Daten und ein bisschen Pause fürs Stopbit (die ich mir gespart hab). Mit dem Wissen, wie lange ein NOP in der CPU dauert die Timings angepasst und los geht's. Mit "normalen" USB<>UART-Adaptern hat man allerdings wenig Spaß: meine Implementierung verwendet - der Faulheit wegen - 10 Datenbits und eine ziemlich krumme Baudrate, die halt einfach gerade gepasst hat. Der Logic Analyzer kann das, die meisten Wandler aber nicht. Aber wer will schon Interoperabilität? Das Ende vom Lied: die Berechnung von oben ist hinreichend genau. == Einbau == Dank der Magnete (Sensor + LEDs) und der Gravitation (Akkus und Mikrocontroller) lässt sich alles befestigen, wo es hin soll. Die Feinausrichtung des Reed-Kontakts geht schnell und einfach. = Es geht besser = Kein Projekt würde mal zweimal genau gleich machen. So auch hier.! = * LED-Treiber mit FET statt Bipolar-Transistoren und dann auch gleich den gemeinsamen FET zum Schalten der Treiber sparen, indem die Versorgung von den Transistoren direkt vom Mikrocontroller kommt. * Spannungsteiler eine Nummer größer dimensionieren und etwas mehr Ungenauigkeit (who cares?!) in Kauf nehmen. Genauso würde ich im AVR gleich den Watchdog als Taktquelle nehmen. * Als Reed-Kontakt einen Schließer nehmen, ihn durch den Befestigungsmagnet "vorspannen" und das Feld durch den Magnet im Deckel neutralisieren. Geht sicher auch auf länger gut und senkt die Bauteilkosten. * Verringern der Betriebsdauer auf 10 Sekunden. Wer starrt schon 30 Sekunden in einen Briefkastenschlitz? <gallery> Datei:Briefkasten_sch2.png|Der etwas verbesserte Schaltplan </gallery> = Trivia = * Der Freund meiner Nachbarin hält mich jetzt wohl für wahnsinnig, weil ich minutenlang vor dem Briefkasten stand und ihn öffnete und schloss ohne ihn zu bemerken. Warum schleicht er auch so herum? * Durch die Mechanische Verkopplung kann man das Klicken des Reedkontakts tatsächlich hören. = Download = [[Briefkasten.zip|Schaltplan & Firmware]] [[Category:AVR]] d0224598e23f037b6434a1a08763c094007da3c4 1062 1061 2016-12-31T17:40:34Z Chris 2 kleine Korrekturen wikitext text/x-wiki Zugegeben, es hört sich nicht nur bescheuert an, es ist auch so. Trotzdem hatte ich das Bedürfnis, eine Briefkasteninnenbeleuchtung zu bauen. Warum? Nein, nicht (nur) weil ich es kann, sondern weil sie durchaus praktisch ist = Problemstellung = Die Briefkästen vom Mietshaus hier sind freistehend und in der dunklen Jahreszeit sieht man durch aufgrund der etwas ungünstig installierten Außenbeleuchtung den Einwurf nicht, ob Post gekommen ist. Durch das Öffnen der Frontklappe sieht und bekommt man zwar den Inhalt, aber dazu bin ich schlicht zu faul. Umbauten müssen rückstandsfrei sein, schließlich will ichs nicht mit meinen Vermietern verscherzen. = Idee = In den Briefkasten soll mindestens eine LED, die durch das Öffnen des Deckels aktiviert wird. Die Befestigung findet über Magnete statt, die Stromversorgung durch Batterien. Damit diese nicht unnötig leergesaugt werden, soll die Beleuchtung zeitlich begrenzt sein. = Umsetzung = Zumindest bei der LED ist die Sache schnell klar: weiße PLCC2 liegen hier mehr als genug herum. Um sie sinnvoll zu betreiben, kommen 3 Mignon-Batterien in Serie zum Einsatz. Bei 3,3 Volt (also wenn die Zellen schon halb-platt sind) sind 7 mA mehr als genug, der passende Widerstand hierfür wäre 171 Ohm. Wäre, weil ein einfacher Vorwiderstand an dieser Stelle dumm ist - die Batteriespannung wird mit dem Ladestand fallen - und damit der Strom durch die LED. == LED-Treiber == Besser ist es deshalb, eine Konstantstromquelle zu verwenden. Die lässt sich sehr einfach aufbauen, zwei Transistoren und zwei Widerstände reichen. Der Strom wird über den unteren Widerstand und Transistor definiert: letzterer wird leitend, wenn seine Basis-Emitter-Spannung über ca. 0,7 Volt steigt - diese Spannung muss beim gewünschten Strom eingeprägt werden. Für den Widerstand gilt also: :<math>\textrm{R}=\frac{0.7}{\textrm{I}_\textrm{out}}</math> Der obere Transistor steuert den Strom durch die LED. Der Widerstand dient lediglich als Pull-up und ist daher eher unkritisch. Wer ihn hinreichend groß Dimensionierung will, muss sich den LED-Strom und den Verstärkungsfaktor ansehen. Die mechanische Integration ist einfach: ich habe noch kleine Leiterkärtchen, eigentlich für einen anderen Zweck, aber es passt alles für diese Schaltung drauf. Schrumpfschlauch drüber, kleine Magnete ran, nochmal Schrumpfschlauch. <gallery> Datei:Einfacher_LED-Treiber.png|Schaltplan des einfachen LED-Treibers Datei:Briefkasten_led.jpg|Aufgebauter LED-Triber mit LED, Magnet und Schrumpfschlauch </gallery> Bilder von den Innereien gibt es leider keine. == Schalter == Für die Erkennung ob der Deckel offen ist gibt es viele Möglichkeiten: mechanischer Taster, Näherungssensoren, Neigungsschalter, Hallswitches, etc.. Mechanische Schalter brauchen in aller Regel viel Kraft (und viel Gegenkraft kann ich bei der Montage nicht bieten) und sind oft empfindlich auf Feuchte. Viele Näherungssensoren (optisch, kapazitiv und induktiv) sind aktiv und haben einen relativ großen Ruhestrom. Nichts für langen Batteriebetrieb. Neigungsschalter geht, war aber früher dank Quecksilber eine ziemliche Sauerei; die aktuellen sind wahrscheinlich besser aber ich habe Vorbehalte. Schlussendlich habe ich einen Reed-Kontakt verwendet. Hermetisch abgeschlossen, kraftfrei und kein Ruhestrom. Wenn man mechanisch faul ist oder nicht genug Grips in der Birne hat, braucht man einen Öffner - genau das (bzw. einen Wechsler) habe ich bestellt. Um die Integration vorweg zu nehmen: der Kontakt ist auf einer kleinen länglichen Leiterkarte gelandet - lang genug, um einen Magnet zur Montage am Briefkasten verwenden zu können. Jetzt kommt auch die Sache mit dem Grips: Der "Montagemagnet" war stark genug, damit das durch das Metall laufende Feld den Kontakt öffnete. Mit geschickter Positionierung beider Magnete (der zur Montage und dem im Deckel) hätte ich die Felder so ausrichten können, dass sie sich im Deckel-zu-Fall neutralisiert hätten. Hätte-hätte... Aber auch so funktioniert es. Um vor Feuchtigkeit besser geschützt zu sein, kommt alles in Schrumpfschlauch und wird natürlich auf der etwas besser geschützten Seite des Briefkastens installiert. <gallery> Datei:Briefkasten_sensor.jpg|unten: Reedschalter auf Leiterkarte mit Magnet, oben (überbelichtet): Magnet </gallery> == Abschaltautomatik == {{Infobox AVR | Typ = ATtiny45 | Takt = 0,6 | FuseH = FF | FuseL = 61 }} Eigentlich wäre diese prädestiniert für eine Analogschaltung oder einen NE555. Schlussendlich wurde es aber ein ATtiny13. Der ist mit der Aufgabe zwar gänzlich unterfordert, braucht dafür im Schlaf nahezu keinen Strom und zudem fast keine Außenbeschaltung Das Programm könnte sehr einfach sein: Port initialisieren, Pin an, warten, Pin aus. Mit 4,8 MHz Takt braucht der Controller einige Milliampere, was in beiderlei Hinsicht unnötig viel ist. Über die CLKDIV-Fuse kann der Takt auf ein Achtel reduziert werden - besser aber trotzdem nicht überragend. Was ich beim Programmieren übersehen habe: den Watchdog als Taktquelle - 128 kHz und noch etwas stromsparender. Im [http://www.atmel.com/images/doc2535.pdf Datenblatt] kann man sich dazu Figure 19-1 und 19-5 anschauen. Demnach braucht der Chip bei 600 kHz (bei externer Taktquelle) zwischen 0,3 und 0,5 mA - mit dem Watchdog wären es lediglich 0,06 bis 0,09 mA. Statt warten per Delay kann man auch den internen Timer verwenden und die CPU bei Overflow wecken. Nur leider kann man mit weiterlaufendem Takt den Tiny nicht tief genug schlafen schicken, damit es richtig gut wird. Geht man in den Tiefschlaf, bleibt der Takt komplett weg und das war dann für den Timer. Glücklicherweise kann man den Watchdog so konfigurieren, dass er keinen Reset sondern einen Interrupt auslöst. Da er einen eigenen Oszillator hat, ist er zudem unabhängig vom Systemtakt. Sein Vorteiler lässt sich bis in den angenehmen Sekundenbereich einstellen. Im Power-Down und aktivem Watchdog braucht der Prozessor (Figure 19-14) zwischen 4,5 und 7,0 µA. Nachdem das Programm durch ist und sich der Bursche schlafen legt, sinkt der Stromverbrauch (Figure 19-13) auf sehr niedrige 0,2 bis 1,2 µA. Wo liegt nochmal die Selbstentladung von Alkali-Zellen? == Batteriewächter == Darf's ein bisschen mehr sein? Der ATtiny13 hat einen ADC, warum also nicht noch zusätzlich eine Warnung für bald leere Batterien einbauen? Einige AVRs können den ADC verkehrte Welt spielen lassen: Man kann die interne Referenz als Eingang wählen und die Versorgungsspannung als Referenz. Dadurch wird das Ergebnis zwar reziprok aber die Messung braucht keine externe Beschaltung und ist zudem sehr stromsparend. Geht hier leider nicht (Figure 14-1). Es muss also ein externer Spannungsteiler her. Der braucht permanent einen gewissen Strom und das ist Mist. Man kann die Widerstände zwar nach oben dimensionieren, dann wird die Messung durch ADC-bedingte Verfälschungen ungenauer. Ich bin einen etwas faulen (im Sinne von: warum mehr Zeit verschwenden) Kompromiss eingegangen: Der Spannungsteiler wird vom Schaltsignal für die LEDs versorgt. Dadurch haut der Strom nur für die maximal 30 Sekunden ab und zugleich hat der FET einen Pull-Dowm am Gate, falls der IO doch mal floatet. Der Treiber im AVR ist einen leichten Spannungsabfall haben, aber zum einen kann man kalibrieren und zum anderen wird keine besonders hohe Genauigkeit benötigt. Bei der Dimensionierung muss man - wie bereits erwähnt - darauf achten, dass die Messung halbwegs sauber funktioniert aber gleichzeitig nicht unnötig viel Strom verbraucht wird. Natürlich muss auch der Teiler passen. Für diesen Zweck verwende ich gerne [https://www.muellerzumhagen.de/widerstand-ist-zwecklos-pointless-resistance/ Widerstand ist zwecklos], das die Paarung 33 kOhm (top) und 10 kOhm (bottom) ausspuckte. Damit ergibt sich eine maximal messbare Spannung von 4,73 V und ein Stromverbrauch von nicht ganz 105 µA bei 4,5 V. Die Auflösung wäre damit nicht ganz 4,6 mV - deutlich mehr als genug. Der ADC-Wert berechnet sich theoretisch wie folgt: :<math>\textrm{ADC}= \textrm{U}_{\textrm{bat}} \cdot \frac{10\textrm{ k}\Omega}{10\textrm{ k}\Omega+33\textrm{ k}\Omega} \cdot \frac{1024}{1.1\textrm{ V}}</math> Die Messung selbst ist geradeaus: Auswählen der Referenz und Eingang (PB4), Takt festlegen, Interrupt an und los geht's. Um etwas sinnvolles zu machen während die Messung durchgeführt wird, legt sich der Kern schlafen und wird wieder geweckt, sobald diese durch ist (sei(); nicht vergessen!). Anschließend wird der ADC-Wert ausgelesen und der Block wieder deaktiviert. Um etwas bessere Ergebnisse zu erlangen, wird die Batteriespannung nicht direkt nach dem Start sondern nach einer Sekunde durchgeführt. Dadurch lassen sich zwei Dinge verknüpfen: Die Batterien sehen eine Last und man ist am richtigen Zeitpunkt, um die LEDs kurz auszuschalten. <gallery> Datei:Briefkasten_sch1.png|Schaltung </gallery> === Kalibrierung === Aufgrund der Beschaltung sah ich mich genötigt, den ADC zu testen. Der einfachste Weg dafür wäre UART, den es aber nicht gibt. Zumindest nicht in Hardware. Das Format ist relativ einfach, siehe [[wpde:Universal_Asynchronous_Receiver_Transmitter|Wikipedia]]. Idle high, Startbit, Daten und ein bisschen Pause fürs Stopbit (die ich mir gespart hab). Mit dem Wissen, wie lange ein NOP in der CPU dauert die Timings angepasst und los geht's. Mit "normalen" USB<>UART-Adaptern hat man allerdings wenig Spaß: meine Implementierung verwendet - der Faulheit wegen - 10 Datenbits und eine ziemlich krumme Baudrate, die halt einfach gerade gepasst hat. Der Logic Analyzer kann das, die meisten Wandler aber nicht. Aber wer will schon Interoperabilität? Das Ende vom Lied: die Berechnung von oben ist hinreichend genau. == Einbau == Dank der Magnete (Sensor + LEDs) und der Gravitation (Akkus und Mikrocontroller) lässt sich alles befestigen, wo es hin soll. Die Feinausrichtung des Reed-Kontakts geht schnell und einfach. = Es geht besser = Kein Projekt würde mal zweimal genau gleich machen. So auch hier.! = * LED-Treiber mit FET statt Bipolar-Transistoren aufbauen und dann auch gleich den gemeinsamen FET zum Schalten der Treiber sparen, indem die Versorgung von den Transistoren direkt vom Mikrocontroller kommt. * Spannungsteiler eine Nummer größer dimensionieren und etwas mehr Ungenauigkeit (who cares?!) in Kauf nehmen. Genauso würde ich im AVR gleich den Watchdog als Taktquelle nehmen. * Als Reed-Kontakt einen Schließer nehmen, ihn durch den Befestigungsmagnet "vorspannen" und das Feld durch den Magnet im Deckel neutralisieren. Geht sicher auch auf länger gut und senkt die Bauteilkosten. * Verringern der Betriebsdauer auf 10 Sekunden. Wer starrt schon 30 Sekunden in einen Briefkastenschlitz? <gallery> Datei:Briefkasten_sch2.png|Der etwas verbesserte Schaltplan </gallery> = Trivia = * Der Freund meiner Nachbarin hält mich jetzt wohl für wahnsinnig, weil ich minutenlang vor dem Briefkasten stand und ihn öffnete und schloss ohne ihn zu bemerken. Warum schleicht er auch so herum? * Durch die Mechanische Verkopplung kann man das Klicken des Reedkontakts tatsächlich hören. = Download = [[Briefkasten.zip|Schaltplan & Firmware]] [[Category:AVR]] df4f60e2f8d888b1a806274fd6b8b33f62dc1b3e 1063 1062 2016-12-31T17:41:35Z Chris 2 /* Download */ Namensraum vergessen wikitext text/x-wiki Zugegeben, es hört sich nicht nur bescheuert an, es ist auch so. Trotzdem hatte ich das Bedürfnis, eine Briefkasteninnenbeleuchtung zu bauen. Warum? Nein, nicht (nur) weil ich es kann, sondern weil sie durchaus praktisch ist = Problemstellung = Die Briefkästen vom Mietshaus hier sind freistehend und in der dunklen Jahreszeit sieht man durch aufgrund der etwas ungünstig installierten Außenbeleuchtung den Einwurf nicht, ob Post gekommen ist. Durch das Öffnen der Frontklappe sieht und bekommt man zwar den Inhalt, aber dazu bin ich schlicht zu faul. Umbauten müssen rückstandsfrei sein, schließlich will ichs nicht mit meinen Vermietern verscherzen. = Idee = In den Briefkasten soll mindestens eine LED, die durch das Öffnen des Deckels aktiviert wird. Die Befestigung findet über Magnete statt, die Stromversorgung durch Batterien. Damit diese nicht unnötig leergesaugt werden, soll die Beleuchtung zeitlich begrenzt sein. = Umsetzung = Zumindest bei der LED ist die Sache schnell klar: weiße PLCC2 liegen hier mehr als genug herum. Um sie sinnvoll zu betreiben, kommen 3 Mignon-Batterien in Serie zum Einsatz. Bei 3,3 Volt (also wenn die Zellen schon halb-platt sind) sind 7 mA mehr als genug, der passende Widerstand hierfür wäre 171 Ohm. Wäre, weil ein einfacher Vorwiderstand an dieser Stelle dumm ist - die Batteriespannung wird mit dem Ladestand fallen - und damit der Strom durch die LED. == LED-Treiber == Besser ist es deshalb, eine Konstantstromquelle zu verwenden. Die lässt sich sehr einfach aufbauen, zwei Transistoren und zwei Widerstände reichen. Der Strom wird über den unteren Widerstand und Transistor definiert: letzterer wird leitend, wenn seine Basis-Emitter-Spannung über ca. 0,7 Volt steigt - diese Spannung muss beim gewünschten Strom eingeprägt werden. Für den Widerstand gilt also: :<math>\textrm{R}=\frac{0.7}{\textrm{I}_\textrm{out}}</math> Der obere Transistor steuert den Strom durch die LED. Der Widerstand dient lediglich als Pull-up und ist daher eher unkritisch. Wer ihn hinreichend groß Dimensionierung will, muss sich den LED-Strom und den Verstärkungsfaktor ansehen. Die mechanische Integration ist einfach: ich habe noch kleine Leiterkärtchen, eigentlich für einen anderen Zweck, aber es passt alles für diese Schaltung drauf. Schrumpfschlauch drüber, kleine Magnete ran, nochmal Schrumpfschlauch. <gallery> Datei:Einfacher_LED-Treiber.png|Schaltplan des einfachen LED-Treibers Datei:Briefkasten_led.jpg|Aufgebauter LED-Triber mit LED, Magnet und Schrumpfschlauch </gallery> Bilder von den Innereien gibt es leider keine. == Schalter == Für die Erkennung ob der Deckel offen ist gibt es viele Möglichkeiten: mechanischer Taster, Näherungssensoren, Neigungsschalter, Hallswitches, etc.. Mechanische Schalter brauchen in aller Regel viel Kraft (und viel Gegenkraft kann ich bei der Montage nicht bieten) und sind oft empfindlich auf Feuchte. Viele Näherungssensoren (optisch, kapazitiv und induktiv) sind aktiv und haben einen relativ großen Ruhestrom. Nichts für langen Batteriebetrieb. Neigungsschalter geht, war aber früher dank Quecksilber eine ziemliche Sauerei; die aktuellen sind wahrscheinlich besser aber ich habe Vorbehalte. Schlussendlich habe ich einen Reed-Kontakt verwendet. Hermetisch abgeschlossen, kraftfrei und kein Ruhestrom. Wenn man mechanisch faul ist oder nicht genug Grips in der Birne hat, braucht man einen Öffner - genau das (bzw. einen Wechsler) habe ich bestellt. Um die Integration vorweg zu nehmen: der Kontakt ist auf einer kleinen länglichen Leiterkarte gelandet - lang genug, um einen Magnet zur Montage am Briefkasten verwenden zu können. Jetzt kommt auch die Sache mit dem Grips: Der "Montagemagnet" war stark genug, damit das durch das Metall laufende Feld den Kontakt öffnete. Mit geschickter Positionierung beider Magnete (der zur Montage und dem im Deckel) hätte ich die Felder so ausrichten können, dass sie sich im Deckel-zu-Fall neutralisiert hätten. Hätte-hätte... Aber auch so funktioniert es. Um vor Feuchtigkeit besser geschützt zu sein, kommt alles in Schrumpfschlauch und wird natürlich auf der etwas besser geschützten Seite des Briefkastens installiert. <gallery> Datei:Briefkasten_sensor.jpg|unten: Reedschalter auf Leiterkarte mit Magnet, oben (überbelichtet): Magnet </gallery> == Abschaltautomatik == {{Infobox AVR | Typ = ATtiny45 | Takt = 0,6 | FuseH = FF | FuseL = 61 }} Eigentlich wäre diese prädestiniert für eine Analogschaltung oder einen NE555. Schlussendlich wurde es aber ein ATtiny13. Der ist mit der Aufgabe zwar gänzlich unterfordert, braucht dafür im Schlaf nahezu keinen Strom und zudem fast keine Außenbeschaltung Das Programm könnte sehr einfach sein: Port initialisieren, Pin an, warten, Pin aus. Mit 4,8 MHz Takt braucht der Controller einige Milliampere, was in beiderlei Hinsicht unnötig viel ist. Über die CLKDIV-Fuse kann der Takt auf ein Achtel reduziert werden - besser aber trotzdem nicht überragend. Was ich beim Programmieren übersehen habe: den Watchdog als Taktquelle - 128 kHz und noch etwas stromsparender. Im [http://www.atmel.com/images/doc2535.pdf Datenblatt] kann man sich dazu Figure 19-1 und 19-5 anschauen. Demnach braucht der Chip bei 600 kHz (bei externer Taktquelle) zwischen 0,3 und 0,5 mA - mit dem Watchdog wären es lediglich 0,06 bis 0,09 mA. Statt warten per Delay kann man auch den internen Timer verwenden und die CPU bei Overflow wecken. Nur leider kann man mit weiterlaufendem Takt den Tiny nicht tief genug schlafen schicken, damit es richtig gut wird. Geht man in den Tiefschlaf, bleibt der Takt komplett weg und das war dann für den Timer. Glücklicherweise kann man den Watchdog so konfigurieren, dass er keinen Reset sondern einen Interrupt auslöst. Da er einen eigenen Oszillator hat, ist er zudem unabhängig vom Systemtakt. Sein Vorteiler lässt sich bis in den angenehmen Sekundenbereich einstellen. Im Power-Down und aktivem Watchdog braucht der Prozessor (Figure 19-14) zwischen 4,5 und 7,0 µA. Nachdem das Programm durch ist und sich der Bursche schlafen legt, sinkt der Stromverbrauch (Figure 19-13) auf sehr niedrige 0,2 bis 1,2 µA. Wo liegt nochmal die Selbstentladung von Alkali-Zellen? == Batteriewächter == Darf's ein bisschen mehr sein? Der ATtiny13 hat einen ADC, warum also nicht noch zusätzlich eine Warnung für bald leere Batterien einbauen? Einige AVRs können den ADC verkehrte Welt spielen lassen: Man kann die interne Referenz als Eingang wählen und die Versorgungsspannung als Referenz. Dadurch wird das Ergebnis zwar reziprok aber die Messung braucht keine externe Beschaltung und ist zudem sehr stromsparend. Geht hier leider nicht (Figure 14-1). Es muss also ein externer Spannungsteiler her. Der braucht permanent einen gewissen Strom und das ist Mist. Man kann die Widerstände zwar nach oben dimensionieren, dann wird die Messung durch ADC-bedingte Verfälschungen ungenauer. Ich bin einen etwas faulen (im Sinne von: warum mehr Zeit verschwenden) Kompromiss eingegangen: Der Spannungsteiler wird vom Schaltsignal für die LEDs versorgt. Dadurch haut der Strom nur für die maximal 30 Sekunden ab und zugleich hat der FET einen Pull-Dowm am Gate, falls der IO doch mal floatet. Der Treiber im AVR ist einen leichten Spannungsabfall haben, aber zum einen kann man kalibrieren und zum anderen wird keine besonders hohe Genauigkeit benötigt. Bei der Dimensionierung muss man - wie bereits erwähnt - darauf achten, dass die Messung halbwegs sauber funktioniert aber gleichzeitig nicht unnötig viel Strom verbraucht wird. Natürlich muss auch der Teiler passen. Für diesen Zweck verwende ich gerne [https://www.muellerzumhagen.de/widerstand-ist-zwecklos-pointless-resistance/ Widerstand ist zwecklos], das die Paarung 33 kOhm (top) und 10 kOhm (bottom) ausspuckte. Damit ergibt sich eine maximal messbare Spannung von 4,73 V und ein Stromverbrauch von nicht ganz 105 µA bei 4,5 V. Die Auflösung wäre damit nicht ganz 4,6 mV - deutlich mehr als genug. Der ADC-Wert berechnet sich theoretisch wie folgt: :<math>\textrm{ADC}= \textrm{U}_{\textrm{bat}} \cdot \frac{10\textrm{ k}\Omega}{10\textrm{ k}\Omega+33\textrm{ k}\Omega} \cdot \frac{1024}{1.1\textrm{ V}}</math> Die Messung selbst ist geradeaus: Auswählen der Referenz und Eingang (PB4), Takt festlegen, Interrupt an und los geht's. Um etwas sinnvolles zu machen während die Messung durchgeführt wird, legt sich der Kern schlafen und wird wieder geweckt, sobald diese durch ist (sei(); nicht vergessen!). Anschließend wird der ADC-Wert ausgelesen und der Block wieder deaktiviert. Um etwas bessere Ergebnisse zu erlangen, wird die Batteriespannung nicht direkt nach dem Start sondern nach einer Sekunde durchgeführt. Dadurch lassen sich zwei Dinge verknüpfen: Die Batterien sehen eine Last und man ist am richtigen Zeitpunkt, um die LEDs kurz auszuschalten. <gallery> Datei:Briefkasten_sch1.png|Schaltung </gallery> === Kalibrierung === Aufgrund der Beschaltung sah ich mich genötigt, den ADC zu testen. Der einfachste Weg dafür wäre UART, den es aber nicht gibt. Zumindest nicht in Hardware. Das Format ist relativ einfach, siehe [[wpde:Universal_Asynchronous_Receiver_Transmitter|Wikipedia]]. Idle high, Startbit, Daten und ein bisschen Pause fürs Stopbit (die ich mir gespart hab). Mit dem Wissen, wie lange ein NOP in der CPU dauert die Timings angepasst und los geht's. Mit "normalen" USB<>UART-Adaptern hat man allerdings wenig Spaß: meine Implementierung verwendet - der Faulheit wegen - 10 Datenbits und eine ziemlich krumme Baudrate, die halt einfach gerade gepasst hat. Der Logic Analyzer kann das, die meisten Wandler aber nicht. Aber wer will schon Interoperabilität? Das Ende vom Lied: die Berechnung von oben ist hinreichend genau. == Einbau == Dank der Magnete (Sensor + LEDs) und der Gravitation (Akkus und Mikrocontroller) lässt sich alles befestigen, wo es hin soll. Die Feinausrichtung des Reed-Kontakts geht schnell und einfach. = Es geht besser = Kein Projekt würde mal zweimal genau gleich machen. So auch hier.! = * LED-Treiber mit FET statt Bipolar-Transistoren aufbauen und dann auch gleich den gemeinsamen FET zum Schalten der Treiber sparen, indem die Versorgung von den Transistoren direkt vom Mikrocontroller kommt. * Spannungsteiler eine Nummer größer dimensionieren und etwas mehr Ungenauigkeit (who cares?!) in Kauf nehmen. Genauso würde ich im AVR gleich den Watchdog als Taktquelle nehmen. * Als Reed-Kontakt einen Schließer nehmen, ihn durch den Befestigungsmagnet "vorspannen" und das Feld durch den Magnet im Deckel neutralisieren. Geht sicher auch auf länger gut und senkt die Bauteilkosten. * Verringern der Betriebsdauer auf 10 Sekunden. Wer starrt schon 30 Sekunden in einen Briefkastenschlitz? <gallery> Datei:Briefkasten_sch2.png|Der etwas verbesserte Schaltplan </gallery> = Trivia = * Der Freund meiner Nachbarin hält mich jetzt wohl für wahnsinnig, weil ich minutenlang vor dem Briefkasten stand und ihn öffnete und schloss ohne ihn zu bemerken. Warum schleicht er auch so herum? * Durch die Mechanische Verkopplung kann man das Klicken des Reedkontakts tatsächlich hören. = Download = [[Datei:Briefkasten.zip|Schaltplan & Firmware]] [[Category:AVR]] 3430e18d1284beb4c289c1ab8602d4fcd06a45f4 1064 1063 2016-12-31T17:43:28Z Chris 2 wikitext text/x-wiki Zugegeben, es hört sich nicht nur bescheuert an, es ist auch so. Trotzdem hatte ich das Bedürfnis, eine Briefkasteninnenbeleuchtung zu bauen. Warum? Nein, nicht (nur) weil ich es kann, sondern weil sie durchaus praktisch ist = Problemstellung = Die Briefkästen vom Mietshaus hier sind freistehend und in der dunklen Jahreszeit sieht man durch aufgrund der etwas ungünstig installierten Außenbeleuchtung den Einwurf nicht, ob Post gekommen ist. Durch das Öffnen der Frontklappe sieht und bekommt man zwar den Inhalt, aber dazu bin ich schlicht zu faul. Umbauten müssen rückstandsfrei sein, schließlich will ichs nicht mit meinen Vermietern verscherzen. = Idee = In den Briefkasten soll mindestens eine LED, die durch das Öffnen des Deckels aktiviert wird. Die Befestigung findet über Magnete statt, die Stromversorgung durch Batterien. Damit diese nicht unnötig leergesaugt werden, soll die Beleuchtung zeitlich begrenzt sein. = Umsetzung = Zumindest bei der LED ist die Sache schnell klar: weiße PLCC2 liegen hier mehr als genug herum. Um sie sinnvoll zu betreiben, kommen 3 Mignon-Batterien in Serie zum Einsatz. Bei 3,3 Volt (also wenn die Zellen schon halb-platt sind) sind 7 mA mehr als genug, der passende Widerstand hierfür wäre 171 Ohm. Wäre, weil ein einfacher Vorwiderstand an dieser Stelle dumm ist - die Batteriespannung wird mit dem Ladestand fallen - und damit der Strom durch die LED. == LED-Treiber == Besser ist es deshalb, eine Konstantstromquelle zu verwenden. Die lässt sich sehr einfach aufbauen, zwei Transistoren und zwei Widerstände reichen. Der Strom wird über den unteren Widerstand und Transistor definiert: letzterer wird leitend, wenn seine Basis-Emitter-Spannung über ca. 0,7 Volt steigt - diese Spannung muss beim gewünschten Strom eingeprägt werden. Für den Widerstand gilt also: :<math>\textrm{R}=\frac{0.7}{\textrm{I}_\textrm{out}}</math> Der obere Transistor steuert den Strom durch die LED. Der Widerstand dient lediglich als Pull-up und ist daher eher unkritisch. Wer ihn hinreichend groß Dimensionierung will, muss sich den LED-Strom und den Verstärkungsfaktor ansehen. Die mechanische Integration ist einfach: ich habe noch kleine Leiterkärtchen, eigentlich für einen anderen Zweck, aber es passt alles für diese Schaltung drauf. Schrumpfschlauch drüber, kleine Magnete ran, nochmal Schrumpfschlauch. <gallery> Datei:Einfacher_LED-Treiber.png|Schaltplan des einfachen LED-Treibers Datei:Briefkasten_led.jpg|Aufgebauter LED-Triber mit LED, Magnet und Schrumpfschlauch </gallery> Bilder von den Innereien gibt es leider keine. == Schalter == Für die Erkennung ob der Deckel offen ist gibt es viele Möglichkeiten: mechanischer Taster, Näherungssensoren, Neigungsschalter, Hallswitches, etc.. Mechanische Schalter brauchen in aller Regel viel Kraft (und viel Gegenkraft kann ich bei der Montage nicht bieten) und sind oft empfindlich auf Feuchte. Viele Näherungssensoren (optisch, kapazitiv und induktiv) sind aktiv und haben einen relativ großen Ruhestrom. Nichts für langen Batteriebetrieb. Neigungsschalter geht, war aber früher dank Quecksilber eine ziemliche Sauerei; die aktuellen sind wahrscheinlich besser aber ich habe Vorbehalte. Schlussendlich habe ich einen Reed-Kontakt verwendet. Hermetisch abgeschlossen, kraftfrei und kein Ruhestrom. Wenn man mechanisch faul ist oder nicht genug Grips in der Birne hat, braucht man einen Öffner - genau das (bzw. einen Wechsler) habe ich bestellt. Um die Integration vorweg zu nehmen: der Kontakt ist auf einer kleinen länglichen Leiterkarte gelandet - lang genug, um einen Magnet zur Montage am Briefkasten verwenden zu können. Jetzt kommt auch die Sache mit dem Grips: Der "Montagemagnet" war stark genug, damit das durch das Metall laufende Feld den Kontakt öffnete. Mit geschickter Positionierung beider Magnete (der zur Montage und dem im Deckel) hätte ich die Felder so ausrichten können, dass sie sich im Deckel-zu-Fall neutralisiert hätten. Hätte-hätte... Aber auch so funktioniert es. Um vor Feuchtigkeit besser geschützt zu sein, kommt alles in Schrumpfschlauch und wird natürlich auf der etwas besser geschützten Seite des Briefkastens installiert. <gallery> Datei:Briefkasten_sensor.jpg|unten: Reedschalter auf Leiterkarte mit Magnet, oben (überbelichtet): Magnet </gallery> == Abschaltautomatik == {{Infobox AVR | Typ = ATtiny45 | Takt = 0,6 | FuseH = FF | FuseL = 61 }} Eigentlich wäre diese prädestiniert für eine Analogschaltung oder einen NE555. Schlussendlich wurde es aber ein ATtiny13. Der ist mit der Aufgabe zwar gänzlich unterfordert, braucht dafür im Schlaf nahezu keinen Strom und zudem fast keine Außenbeschaltung Das Programm könnte sehr einfach sein: Port initialisieren, Pin an, warten, Pin aus. Mit 4,8 MHz Takt braucht der Controller einige Milliampere, was in beiderlei Hinsicht unnötig viel ist. Über die CLKDIV-Fuse kann der Takt auf ein Achtel reduziert werden - besser aber trotzdem nicht überragend. Was ich beim Programmieren übersehen habe: den Watchdog als Taktquelle - 128 kHz und noch etwas stromsparender. Im [http://www.atmel.com/images/doc2535.pdf Datenblatt] kann man sich dazu Figure 19-1 und 19-5 anschauen. Demnach braucht der Chip bei 600 kHz (bei externer Taktquelle) zwischen 0,3 und 0,5 mA - mit dem Watchdog wären es lediglich 0,06 bis 0,09 mA. Statt warten per Delay kann man auch den internen Timer verwenden und die CPU bei Overflow wecken. Nur leider kann man mit weiterlaufendem Takt den Tiny nicht tief genug schlafen schicken, damit es richtig gut wird. Geht man in den Tiefschlaf, bleibt der Takt komplett weg und das war dann für den Timer. Glücklicherweise kann man den Watchdog so konfigurieren, dass er keinen Reset sondern einen Interrupt auslöst. Da er einen eigenen Oszillator hat, ist er zudem unabhängig vom Systemtakt. Sein Vorteiler lässt sich bis in den angenehmen Sekundenbereich einstellen. Im Power-Down und aktivem Watchdog braucht der Prozessor (Figure 19-14) zwischen 4,5 und 7,0 µA. Nachdem das Programm durch ist und sich der Bursche schlafen legt, sinkt der Stromverbrauch (Figure 19-13) auf sehr niedrige 0,2 bis 1,2 µA. Wo liegt nochmal die Selbstentladung von Alkali-Zellen? == Batteriewächter == Darf's ein bisschen mehr sein? Der ATtiny13 hat einen ADC, warum also nicht noch zusätzlich eine Warnung für bald leere Batterien einbauen? Einige AVRs können den ADC verkehrte Welt spielen lassen: Man kann die interne Referenz als Eingang wählen und die Versorgungsspannung als Referenz. Dadurch wird das Ergebnis zwar reziprok aber die Messung braucht keine externe Beschaltung und ist zudem sehr stromsparend. Geht hier leider nicht (Figure 14-1). Es muss also ein externer Spannungsteiler her. Der braucht permanent einen gewissen Strom und das ist Mist. Man kann die Widerstände zwar nach oben dimensionieren, dann wird die Messung durch ADC-bedingte Verfälschungen ungenauer. Ich bin einen etwas faulen (im Sinne von: warum mehr Zeit verschwenden) Kompromiss eingegangen: Der Spannungsteiler wird vom Schaltsignal für die LEDs versorgt. Dadurch haut der Strom nur für die maximal 30 Sekunden ab und zugleich hat der FET einen Pull-Dowm am Gate, falls der IO doch mal floatet. Der Treiber im AVR ist einen leichten Spannungsabfall haben, aber zum einen kann man kalibrieren und zum anderen wird keine besonders hohe Genauigkeit benötigt. Bei der Dimensionierung muss man - wie bereits erwähnt - darauf achten, dass die Messung halbwegs sauber funktioniert aber gleichzeitig nicht unnötig viel Strom verbraucht wird. Natürlich muss auch der Teiler passen. Für diesen Zweck verwende ich gerne [https://www.muellerzumhagen.de/widerstand-ist-zwecklos-pointless-resistance/ Widerstand ist zwecklos], das die Paarung 33 kOhm (top) und 10 kOhm (bottom) ausspuckte. Damit ergibt sich eine maximal messbare Spannung von 4,73 V und ein Stromverbrauch von nicht ganz 105 µA bei 4,5 V. Die Auflösung wäre damit nicht ganz 4,6 mV - deutlich mehr als genug. Der ADC-Wert berechnet sich theoretisch wie folgt: :<math>\textrm{ADC}= \textrm{U}_{\textrm{bat}} \cdot \frac{10\textrm{ k}\Omega}{10\textrm{ k}\Omega+33\textrm{ k}\Omega} \cdot \frac{1024}{1.1\textrm{ V}}</math> Die Messung selbst ist geradeaus: Auswählen der Referenz und Eingang (PB4), Takt festlegen, Interrupt an und los geht's. Um etwas sinnvolles zu machen während die Messung durchgeführt wird, legt sich der Kern schlafen und wird wieder geweckt, sobald diese durch ist (sei(); nicht vergessen!). Anschließend wird der ADC-Wert ausgelesen und der Block wieder deaktiviert. Um etwas bessere Ergebnisse zu erlangen, wird die Batteriespannung nicht direkt nach dem Start sondern nach einer Sekunde durchgeführt. Dadurch lassen sich zwei Dinge verknüpfen: Die Batterien sehen eine Last und man ist am richtigen Zeitpunkt, um die LEDs kurz auszuschalten. <gallery> Datei:Briefkasten_sch1.png|Schaltung </gallery> === Kalibrierung === Aufgrund der Beschaltung sah ich mich genötigt, den ADC zu testen. Der einfachste Weg dafür wäre UART, den es aber nicht gibt. Zumindest nicht in Hardware. Das Format ist relativ einfach, siehe [[wpde:Universal_Asynchronous_Receiver_Transmitter|Wikipedia]]. Idle high, Startbit, Daten und ein bisschen Pause fürs Stopbit (die ich mir gespart hab). Mit dem Wissen, wie lange ein NOP in der CPU dauert die Timings angepasst und los geht's. Mit "normalen" USB<>UART-Adaptern hat man allerdings wenig Spaß: meine Implementierung verwendet - der Faulheit wegen - 10 Datenbits und eine ziemlich krumme Baudrate, die halt einfach gerade gepasst hat. Der Logic Analyzer kann das, die meisten Wandler aber nicht. Aber wer will schon Interoperabilität? Das Ende vom Lied: die Berechnung von oben ist hinreichend genau. == Einbau == Dank der Magnete (Sensor + LEDs) und der Gravitation (Akkus und Mikrocontroller) lässt sich alles befestigen, wo es hin soll. Die Feinausrichtung des Reed-Kontakts geht schnell und einfach. = Es geht besser = Kein Projekt würde mal zweimal genau gleich machen. So auch hier. * LED-Treiber mit FET statt Bipolar-Transistoren aufbauen und dann auch gleich den gemeinsamen FET zum Schalten der Treiber sparen, indem die Versorgung von den Transistoren direkt vom Mikrocontroller kommt. * Spannungsteiler eine Nummer größer dimensionieren und etwas mehr Ungenauigkeit (who cares?!) in Kauf nehmen. Genauso würde ich im AVR gleich den Watchdog als Taktquelle nehmen. * Als Reed-Kontakt einen Schließer nehmen, ihn durch den Befestigungsmagnet "vorspannen" und das Feld durch den Magnet im Deckel neutralisieren. Geht sicher auch auf länger gut und senkt die Bauteilkosten. * Verringern der Betriebsdauer auf 10 Sekunden. Wer starrt schon 30 Sekunden in einen Briefkastenschlitz? <gallery> Datei:Briefkasten_sch2.png|Der etwas verbesserte Schaltplan </gallery> = Ende vom Lied = Es ist wirklich sehr praktisch! = Trivia = * Der Freund meiner Nachbarin hält mich jetzt wohl für wahnsinnig, weil ich minutenlang vor dem Briefkasten stand und ihn öffnete und schloss ohne ihn zu bemerken. Warum schleicht er auch so herum? * Durch die Mechanische Verkopplung kann man das Klicken des Reedkontakts tatsächlich hören. = Download = [[Datei:Briefkasten.zip|Schaltplan & Firmware]] [[Category:AVR]] d8bda657812fd9c7c2e01fb4847b9baa7a4e25ea 1065 1064 2016-12-31T17:43:49Z Chris 2 Leerzeilen entfernt wikitext text/x-wiki Zugegeben, es hört sich nicht nur bescheuert an, es ist auch so. Trotzdem hatte ich das Bedürfnis, eine Briefkasteninnenbeleuchtung zu bauen. Warum? Nein, nicht (nur) weil ich es kann, sondern weil sie durchaus praktisch ist = Problemstellung = Die Briefkästen vom Mietshaus hier sind freistehend und in der dunklen Jahreszeit sieht man durch aufgrund der etwas ungünstig installierten Außenbeleuchtung den Einwurf nicht, ob Post gekommen ist. Durch das Öffnen der Frontklappe sieht und bekommt man zwar den Inhalt, aber dazu bin ich schlicht zu faul. Umbauten müssen rückstandsfrei sein, schließlich will ichs nicht mit meinen Vermietern verscherzen. = Idee = In den Briefkasten soll mindestens eine LED, die durch das Öffnen des Deckels aktiviert wird. Die Befestigung findet über Magnete statt, die Stromversorgung durch Batterien. Damit diese nicht unnötig leergesaugt werden, soll die Beleuchtung zeitlich begrenzt sein. = Umsetzung = Zumindest bei der LED ist die Sache schnell klar: weiße PLCC2 liegen hier mehr als genug herum. Um sie sinnvoll zu betreiben, kommen 3 Mignon-Batterien in Serie zum Einsatz. Bei 3,3 Volt (also wenn die Zellen schon halb-platt sind) sind 7 mA mehr als genug, der passende Widerstand hierfür wäre 171 Ohm. Wäre, weil ein einfacher Vorwiderstand an dieser Stelle dumm ist - die Batteriespannung wird mit dem Ladestand fallen - und damit der Strom durch die LED. == LED-Treiber == Besser ist es deshalb, eine Konstantstromquelle zu verwenden. Die lässt sich sehr einfach aufbauen, zwei Transistoren und zwei Widerstände reichen. Der Strom wird über den unteren Widerstand und Transistor definiert: letzterer wird leitend, wenn seine Basis-Emitter-Spannung über ca. 0,7 Volt steigt - diese Spannung muss beim gewünschten Strom eingeprägt werden. Für den Widerstand gilt also: :<math>\textrm{R}=\frac{0.7}{\textrm{I}_\textrm{out}}</math> Der obere Transistor steuert den Strom durch die LED. Der Widerstand dient lediglich als Pull-up und ist daher eher unkritisch. Wer ihn hinreichend groß Dimensionierung will, muss sich den LED-Strom und den Verstärkungsfaktor ansehen. Die mechanische Integration ist einfach: ich habe noch kleine Leiterkärtchen, eigentlich für einen anderen Zweck, aber es passt alles für diese Schaltung drauf. Schrumpfschlauch drüber, kleine Magnete ran, nochmal Schrumpfschlauch. <gallery> Datei:Einfacher_LED-Treiber.png|Schaltplan des einfachen LED-Treibers Datei:Briefkasten_led.jpg|Aufgebauter LED-Triber mit LED, Magnet und Schrumpfschlauch </gallery> Bilder von den Innereien gibt es leider keine. == Schalter == Für die Erkennung ob der Deckel offen ist gibt es viele Möglichkeiten: mechanischer Taster, Näherungssensoren, Neigungsschalter, Hallswitches, etc.. Mechanische Schalter brauchen in aller Regel viel Kraft (und viel Gegenkraft kann ich bei der Montage nicht bieten) und sind oft empfindlich auf Feuchte. Viele Näherungssensoren (optisch, kapazitiv und induktiv) sind aktiv und haben einen relativ großen Ruhestrom. Nichts für langen Batteriebetrieb. Neigungsschalter geht, war aber früher dank Quecksilber eine ziemliche Sauerei; die aktuellen sind wahrscheinlich besser aber ich habe Vorbehalte. Schlussendlich habe ich einen Reed-Kontakt verwendet. Hermetisch abgeschlossen, kraftfrei und kein Ruhestrom. Wenn man mechanisch faul ist oder nicht genug Grips in der Birne hat, braucht man einen Öffner - genau das (bzw. einen Wechsler) habe ich bestellt. Um die Integration vorweg zu nehmen: der Kontakt ist auf einer kleinen länglichen Leiterkarte gelandet - lang genug, um einen Magnet zur Montage am Briefkasten verwenden zu können. Jetzt kommt auch die Sache mit dem Grips: Der "Montagemagnet" war stark genug, damit das durch das Metall laufende Feld den Kontakt öffnete. Mit geschickter Positionierung beider Magnete (der zur Montage und dem im Deckel) hätte ich die Felder so ausrichten können, dass sie sich im Deckel-zu-Fall neutralisiert hätten. Hätte-hätte... Aber auch so funktioniert es. Um vor Feuchtigkeit besser geschützt zu sein, kommt alles in Schrumpfschlauch und wird natürlich auf der etwas besser geschützten Seite des Briefkastens installiert. <gallery> Datei:Briefkasten_sensor.jpg|unten: Reedschalter auf Leiterkarte mit Magnet, oben (überbelichtet): Magnet </gallery> == Abschaltautomatik == {{Infobox AVR | Typ = ATtiny45 | Takt = 0,6 | FuseH = FF | FuseL = 61 }} Eigentlich wäre diese prädestiniert für eine Analogschaltung oder einen NE555. Schlussendlich wurde es aber ein ATtiny13. Der ist mit der Aufgabe zwar gänzlich unterfordert, braucht dafür im Schlaf nahezu keinen Strom und zudem fast keine Außenbeschaltung Das Programm könnte sehr einfach sein: Port initialisieren, Pin an, warten, Pin aus. Mit 4,8 MHz Takt braucht der Controller einige Milliampere, was in beiderlei Hinsicht unnötig viel ist. Über die CLKDIV-Fuse kann der Takt auf ein Achtel reduziert werden - besser aber trotzdem nicht überragend. Was ich beim Programmieren übersehen habe: den Watchdog als Taktquelle - 128 kHz und noch etwas stromsparender. Im [http://www.atmel.com/images/doc2535.pdf Datenblatt] kann man sich dazu Figure 19-1 und 19-5 anschauen. Demnach braucht der Chip bei 600 kHz (bei externer Taktquelle) zwischen 0,3 und 0,5 mA - mit dem Watchdog wären es lediglich 0,06 bis 0,09 mA. Statt warten per Delay kann man auch den internen Timer verwenden und die CPU bei Overflow wecken. Nur leider kann man mit weiterlaufendem Takt den Tiny nicht tief genug schlafen schicken, damit es richtig gut wird. Geht man in den Tiefschlaf, bleibt der Takt komplett weg und das war dann für den Timer. Glücklicherweise kann man den Watchdog so konfigurieren, dass er keinen Reset sondern einen Interrupt auslöst. Da er einen eigenen Oszillator hat, ist er zudem unabhängig vom Systemtakt. Sein Vorteiler lässt sich bis in den angenehmen Sekundenbereich einstellen. Im Power-Down und aktivem Watchdog braucht der Prozessor (Figure 19-14) zwischen 4,5 und 7,0 µA. Nachdem das Programm durch ist und sich der Bursche schlafen legt, sinkt der Stromverbrauch (Figure 19-13) auf sehr niedrige 0,2 bis 1,2 µA. Wo liegt nochmal die Selbstentladung von Alkali-Zellen? == Batteriewächter == Darf's ein bisschen mehr sein? Der ATtiny13 hat einen ADC, warum also nicht noch zusätzlich eine Warnung für bald leere Batterien einbauen? Einige AVRs können den ADC verkehrte Welt spielen lassen: Man kann die interne Referenz als Eingang wählen und die Versorgungsspannung als Referenz. Dadurch wird das Ergebnis zwar reziprok aber die Messung braucht keine externe Beschaltung und ist zudem sehr stromsparend. Geht hier leider nicht (Figure 14-1). Es muss also ein externer Spannungsteiler her. Der braucht permanent einen gewissen Strom und das ist Mist. Man kann die Widerstände zwar nach oben dimensionieren, dann wird die Messung durch ADC-bedingte Verfälschungen ungenauer. Ich bin einen etwas faulen (im Sinne von: warum mehr Zeit verschwenden) Kompromiss eingegangen: Der Spannungsteiler wird vom Schaltsignal für die LEDs versorgt. Dadurch haut der Strom nur für die maximal 30 Sekunden ab und zugleich hat der FET einen Pull-Dowm am Gate, falls der IO doch mal floatet. Der Treiber im AVR ist einen leichten Spannungsabfall haben, aber zum einen kann man kalibrieren und zum anderen wird keine besonders hohe Genauigkeit benötigt. Bei der Dimensionierung muss man - wie bereits erwähnt - darauf achten, dass die Messung halbwegs sauber funktioniert aber gleichzeitig nicht unnötig viel Strom verbraucht wird. Natürlich muss auch der Teiler passen. Für diesen Zweck verwende ich gerne [https://www.muellerzumhagen.de/widerstand-ist-zwecklos-pointless-resistance/ Widerstand ist zwecklos], das die Paarung 33 kOhm (top) und 10 kOhm (bottom) ausspuckte. Damit ergibt sich eine maximal messbare Spannung von 4,73 V und ein Stromverbrauch von nicht ganz 105 µA bei 4,5 V. Die Auflösung wäre damit nicht ganz 4,6 mV - deutlich mehr als genug. Der ADC-Wert berechnet sich theoretisch wie folgt: :<math>\textrm{ADC}= \textrm{U}_{\textrm{bat}} \cdot \frac{10\textrm{ k}\Omega}{10\textrm{ k}\Omega+33\textrm{ k}\Omega} \cdot \frac{1024}{1.1\textrm{ V}}</math> Die Messung selbst ist geradeaus: Auswählen der Referenz und Eingang (PB4), Takt festlegen, Interrupt an und los geht's. Um etwas sinnvolles zu machen während die Messung durchgeführt wird, legt sich der Kern schlafen und wird wieder geweckt, sobald diese durch ist (sei(); nicht vergessen!). Anschließend wird der ADC-Wert ausgelesen und der Block wieder deaktiviert. Um etwas bessere Ergebnisse zu erlangen, wird die Batteriespannung nicht direkt nach dem Start sondern nach einer Sekunde durchgeführt. Dadurch lassen sich zwei Dinge verknüpfen: Die Batterien sehen eine Last und man ist am richtigen Zeitpunkt, um die LEDs kurz auszuschalten. <gallery> Datei:Briefkasten_sch1.png|Schaltung </gallery> === Kalibrierung === Aufgrund der Beschaltung sah ich mich genötigt, den ADC zu testen. Der einfachste Weg dafür wäre UART, den es aber nicht gibt. Zumindest nicht in Hardware. Das Format ist relativ einfach, siehe [[wpde:Universal_Asynchronous_Receiver_Transmitter|Wikipedia]]. Idle high, Startbit, Daten und ein bisschen Pause fürs Stopbit (die ich mir gespart hab). Mit dem Wissen, wie lange ein NOP in der CPU dauert die Timings angepasst und los geht's. Mit "normalen" USB<>UART-Adaptern hat man allerdings wenig Spaß: meine Implementierung verwendet - der Faulheit wegen - 10 Datenbits und eine ziemlich krumme Baudrate, die halt einfach gerade gepasst hat. Der Logic Analyzer kann das, die meisten Wandler aber nicht. Aber wer will schon Interoperabilität? Das Ende vom Lied: die Berechnung von oben ist hinreichend genau. == Einbau == Dank der Magnete (Sensor + LEDs) und der Gravitation (Akkus und Mikrocontroller) lässt sich alles befestigen, wo es hin soll. Die Feinausrichtung des Reed-Kontakts geht schnell und einfach. = Es geht besser = Kein Projekt würde mal zweimal genau gleich machen. So auch hier. * LED-Treiber mit FET statt Bipolar-Transistoren aufbauen und dann auch gleich den gemeinsamen FET zum Schalten der Treiber sparen, indem die Versorgung von den Transistoren direkt vom Mikrocontroller kommt. * Spannungsteiler eine Nummer größer dimensionieren und etwas mehr Ungenauigkeit (who cares?!) in Kauf nehmen. Genauso würde ich im AVR gleich den Watchdog als Taktquelle nehmen. * Als Reed-Kontakt einen Schließer nehmen, ihn durch den Befestigungsmagnet "vorspannen" und das Feld durch den Magnet im Deckel neutralisieren. Geht sicher auch auf länger gut und senkt die Bauteilkosten. * Verringern der Betriebsdauer auf 10 Sekunden. Wer starrt schon 30 Sekunden in einen Briefkastenschlitz? <gallery> Datei:Briefkasten_sch2.png|Der etwas verbesserte Schaltplan </gallery> = Ende vom Lied = Es ist wirklich sehr praktisch! = Trivia = * Der Freund meiner Nachbarin hält mich jetzt wohl für wahnsinnig, weil ich minutenlang vor dem Briefkasten stand und ihn öffnete und schloss ohne ihn zu bemerken. Warum schleicht er auch so herum? * Durch die Mechanische Verkopplung kann man das Klicken des Reedkontakts tatsächlich hören. = Download = [[Datei:Briefkasten.zip|Schaltplan & Firmware]] [[Category:AVR]] a615a57c7ea5b467bc9cdfa691086ff458c9f16c 1066 1065 2016-12-31T17:44:16Z Chris 2 /* Abschaltautomatik */ AVR korrigiert, ist natürlich ein Tiny13. wikitext text/x-wiki Zugegeben, es hört sich nicht nur bescheuert an, es ist auch so. Trotzdem hatte ich das Bedürfnis, eine Briefkasteninnenbeleuchtung zu bauen. Warum? Nein, nicht (nur) weil ich es kann, sondern weil sie durchaus praktisch ist = Problemstellung = Die Briefkästen vom Mietshaus hier sind freistehend und in der dunklen Jahreszeit sieht man durch aufgrund der etwas ungünstig installierten Außenbeleuchtung den Einwurf nicht, ob Post gekommen ist. Durch das Öffnen der Frontklappe sieht und bekommt man zwar den Inhalt, aber dazu bin ich schlicht zu faul. Umbauten müssen rückstandsfrei sein, schließlich will ichs nicht mit meinen Vermietern verscherzen. = Idee = In den Briefkasten soll mindestens eine LED, die durch das Öffnen des Deckels aktiviert wird. Die Befestigung findet über Magnete statt, die Stromversorgung durch Batterien. Damit diese nicht unnötig leergesaugt werden, soll die Beleuchtung zeitlich begrenzt sein. = Umsetzung = Zumindest bei der LED ist die Sache schnell klar: weiße PLCC2 liegen hier mehr als genug herum. Um sie sinnvoll zu betreiben, kommen 3 Mignon-Batterien in Serie zum Einsatz. Bei 3,3 Volt (also wenn die Zellen schon halb-platt sind) sind 7 mA mehr als genug, der passende Widerstand hierfür wäre 171 Ohm. Wäre, weil ein einfacher Vorwiderstand an dieser Stelle dumm ist - die Batteriespannung wird mit dem Ladestand fallen - und damit der Strom durch die LED. == LED-Treiber == Besser ist es deshalb, eine Konstantstromquelle zu verwenden. Die lässt sich sehr einfach aufbauen, zwei Transistoren und zwei Widerstände reichen. Der Strom wird über den unteren Widerstand und Transistor definiert: letzterer wird leitend, wenn seine Basis-Emitter-Spannung über ca. 0,7 Volt steigt - diese Spannung muss beim gewünschten Strom eingeprägt werden. Für den Widerstand gilt also: :<math>\textrm{R}=\frac{0.7}{\textrm{I}_\textrm{out}}</math> Der obere Transistor steuert den Strom durch die LED. Der Widerstand dient lediglich als Pull-up und ist daher eher unkritisch. Wer ihn hinreichend groß Dimensionierung will, muss sich den LED-Strom und den Verstärkungsfaktor ansehen. Die mechanische Integration ist einfach: ich habe noch kleine Leiterkärtchen, eigentlich für einen anderen Zweck, aber es passt alles für diese Schaltung drauf. Schrumpfschlauch drüber, kleine Magnete ran, nochmal Schrumpfschlauch. <gallery> Datei:Einfacher_LED-Treiber.png|Schaltplan des einfachen LED-Treibers Datei:Briefkasten_led.jpg|Aufgebauter LED-Triber mit LED, Magnet und Schrumpfschlauch </gallery> Bilder von den Innereien gibt es leider keine. == Schalter == Für die Erkennung ob der Deckel offen ist gibt es viele Möglichkeiten: mechanischer Taster, Näherungssensoren, Neigungsschalter, Hallswitches, etc.. Mechanische Schalter brauchen in aller Regel viel Kraft (und viel Gegenkraft kann ich bei der Montage nicht bieten) und sind oft empfindlich auf Feuchte. Viele Näherungssensoren (optisch, kapazitiv und induktiv) sind aktiv und haben einen relativ großen Ruhestrom. Nichts für langen Batteriebetrieb. Neigungsschalter geht, war aber früher dank Quecksilber eine ziemliche Sauerei; die aktuellen sind wahrscheinlich besser aber ich habe Vorbehalte. Schlussendlich habe ich einen Reed-Kontakt verwendet. Hermetisch abgeschlossen, kraftfrei und kein Ruhestrom. Wenn man mechanisch faul ist oder nicht genug Grips in der Birne hat, braucht man einen Öffner - genau das (bzw. einen Wechsler) habe ich bestellt. Um die Integration vorweg zu nehmen: der Kontakt ist auf einer kleinen länglichen Leiterkarte gelandet - lang genug, um einen Magnet zur Montage am Briefkasten verwenden zu können. Jetzt kommt auch die Sache mit dem Grips: Der "Montagemagnet" war stark genug, damit das durch das Metall laufende Feld den Kontakt öffnete. Mit geschickter Positionierung beider Magnete (der zur Montage und dem im Deckel) hätte ich die Felder so ausrichten können, dass sie sich im Deckel-zu-Fall neutralisiert hätten. Hätte-hätte... Aber auch so funktioniert es. Um vor Feuchtigkeit besser geschützt zu sein, kommt alles in Schrumpfschlauch und wird natürlich auf der etwas besser geschützten Seite des Briefkastens installiert. <gallery> Datei:Briefkasten_sensor.jpg|unten: Reedschalter auf Leiterkarte mit Magnet, oben (überbelichtet): Magnet </gallery> == Abschaltautomatik == {{Infobox AVR | Typ = ATtiny13 | Takt = 0,6 | FuseH = FF | FuseL = 61 }} Eigentlich wäre diese prädestiniert für eine Analogschaltung oder einen NE555. Schlussendlich wurde es aber ein ATtiny13. Der ist mit der Aufgabe zwar gänzlich unterfordert, braucht dafür im Schlaf nahezu keinen Strom und zudem fast keine Außenbeschaltung Das Programm könnte sehr einfach sein: Port initialisieren, Pin an, warten, Pin aus. Mit 4,8 MHz Takt braucht der Controller einige Milliampere, was in beiderlei Hinsicht unnötig viel ist. Über die CLKDIV-Fuse kann der Takt auf ein Achtel reduziert werden - besser aber trotzdem nicht überragend. Was ich beim Programmieren übersehen habe: den Watchdog als Taktquelle - 128 kHz und noch etwas stromsparender. Im [http://www.atmel.com/images/doc2535.pdf Datenblatt] kann man sich dazu Figure 19-1 und 19-5 anschauen. Demnach braucht der Chip bei 600 kHz (bei externer Taktquelle) zwischen 0,3 und 0,5 mA - mit dem Watchdog wären es lediglich 0,06 bis 0,09 mA. Statt warten per Delay kann man auch den internen Timer verwenden und die CPU bei Overflow wecken. Nur leider kann man mit weiterlaufendem Takt den Tiny nicht tief genug schlafen schicken, damit es richtig gut wird. Geht man in den Tiefschlaf, bleibt der Takt komplett weg und das war dann für den Timer. Glücklicherweise kann man den Watchdog so konfigurieren, dass er keinen Reset sondern einen Interrupt auslöst. Da er einen eigenen Oszillator hat, ist er zudem unabhängig vom Systemtakt. Sein Vorteiler lässt sich bis in den angenehmen Sekundenbereich einstellen. Im Power-Down und aktivem Watchdog braucht der Prozessor (Figure 19-14) zwischen 4,5 und 7,0 µA. Nachdem das Programm durch ist und sich der Bursche schlafen legt, sinkt der Stromverbrauch (Figure 19-13) auf sehr niedrige 0,2 bis 1,2 µA. Wo liegt nochmal die Selbstentladung von Alkali-Zellen? == Batteriewächter == Darf's ein bisschen mehr sein? Der ATtiny13 hat einen ADC, warum also nicht noch zusätzlich eine Warnung für bald leere Batterien einbauen? Einige AVRs können den ADC verkehrte Welt spielen lassen: Man kann die interne Referenz als Eingang wählen und die Versorgungsspannung als Referenz. Dadurch wird das Ergebnis zwar reziprok aber die Messung braucht keine externe Beschaltung und ist zudem sehr stromsparend. Geht hier leider nicht (Figure 14-1). Es muss also ein externer Spannungsteiler her. Der braucht permanent einen gewissen Strom und das ist Mist. Man kann die Widerstände zwar nach oben dimensionieren, dann wird die Messung durch ADC-bedingte Verfälschungen ungenauer. Ich bin einen etwas faulen (im Sinne von: warum mehr Zeit verschwenden) Kompromiss eingegangen: Der Spannungsteiler wird vom Schaltsignal für die LEDs versorgt. Dadurch haut der Strom nur für die maximal 30 Sekunden ab und zugleich hat der FET einen Pull-Dowm am Gate, falls der IO doch mal floatet. Der Treiber im AVR ist einen leichten Spannungsabfall haben, aber zum einen kann man kalibrieren und zum anderen wird keine besonders hohe Genauigkeit benötigt. Bei der Dimensionierung muss man - wie bereits erwähnt - darauf achten, dass die Messung halbwegs sauber funktioniert aber gleichzeitig nicht unnötig viel Strom verbraucht wird. Natürlich muss auch der Teiler passen. Für diesen Zweck verwende ich gerne [https://www.muellerzumhagen.de/widerstand-ist-zwecklos-pointless-resistance/ Widerstand ist zwecklos], das die Paarung 33 kOhm (top) und 10 kOhm (bottom) ausspuckte. Damit ergibt sich eine maximal messbare Spannung von 4,73 V und ein Stromverbrauch von nicht ganz 105 µA bei 4,5 V. Die Auflösung wäre damit nicht ganz 4,6 mV - deutlich mehr als genug. Der ADC-Wert berechnet sich theoretisch wie folgt: :<math>\textrm{ADC}= \textrm{U}_{\textrm{bat}} \cdot \frac{10\textrm{ k}\Omega}{10\textrm{ k}\Omega+33\textrm{ k}\Omega} \cdot \frac{1024}{1.1\textrm{ V}}</math> Die Messung selbst ist geradeaus: Auswählen der Referenz und Eingang (PB4), Takt festlegen, Interrupt an und los geht's. Um etwas sinnvolles zu machen während die Messung durchgeführt wird, legt sich der Kern schlafen und wird wieder geweckt, sobald diese durch ist (sei(); nicht vergessen!). Anschließend wird der ADC-Wert ausgelesen und der Block wieder deaktiviert. Um etwas bessere Ergebnisse zu erlangen, wird die Batteriespannung nicht direkt nach dem Start sondern nach einer Sekunde durchgeführt. Dadurch lassen sich zwei Dinge verknüpfen: Die Batterien sehen eine Last und man ist am richtigen Zeitpunkt, um die LEDs kurz auszuschalten. <gallery> Datei:Briefkasten_sch1.png|Schaltung </gallery> === Kalibrierung === Aufgrund der Beschaltung sah ich mich genötigt, den ADC zu testen. Der einfachste Weg dafür wäre UART, den es aber nicht gibt. Zumindest nicht in Hardware. Das Format ist relativ einfach, siehe [[wpde:Universal_Asynchronous_Receiver_Transmitter|Wikipedia]]. Idle high, Startbit, Daten und ein bisschen Pause fürs Stopbit (die ich mir gespart hab). Mit dem Wissen, wie lange ein NOP in der CPU dauert die Timings angepasst und los geht's. Mit "normalen" USB<>UART-Adaptern hat man allerdings wenig Spaß: meine Implementierung verwendet - der Faulheit wegen - 10 Datenbits und eine ziemlich krumme Baudrate, die halt einfach gerade gepasst hat. Der Logic Analyzer kann das, die meisten Wandler aber nicht. Aber wer will schon Interoperabilität? Das Ende vom Lied: die Berechnung von oben ist hinreichend genau. == Einbau == Dank der Magnete (Sensor + LEDs) und der Gravitation (Akkus und Mikrocontroller) lässt sich alles befestigen, wo es hin soll. Die Feinausrichtung des Reed-Kontakts geht schnell und einfach. = Es geht besser = Kein Projekt würde mal zweimal genau gleich machen. So auch hier. * LED-Treiber mit FET statt Bipolar-Transistoren aufbauen und dann auch gleich den gemeinsamen FET zum Schalten der Treiber sparen, indem die Versorgung von den Transistoren direkt vom Mikrocontroller kommt. * Spannungsteiler eine Nummer größer dimensionieren und etwas mehr Ungenauigkeit (who cares?!) in Kauf nehmen. Genauso würde ich im AVR gleich den Watchdog als Taktquelle nehmen. * Als Reed-Kontakt einen Schließer nehmen, ihn durch den Befestigungsmagnet "vorspannen" und das Feld durch den Magnet im Deckel neutralisieren. Geht sicher auch auf länger gut und senkt die Bauteilkosten. * Verringern der Betriebsdauer auf 10 Sekunden. Wer starrt schon 30 Sekunden in einen Briefkastenschlitz? <gallery> Datei:Briefkasten_sch2.png|Der etwas verbesserte Schaltplan </gallery> = Ende vom Lied = Es ist wirklich sehr praktisch! = Trivia = * Der Freund meiner Nachbarin hält mich jetzt wohl für wahnsinnig, weil ich minutenlang vor dem Briefkasten stand und ihn öffnete und schloss ohne ihn zu bemerken. Warum schleicht er auch so herum? * Durch die Mechanische Verkopplung kann man das Klicken des Reedkontakts tatsächlich hören. = Download = [[Datei:Briefkasten.zip|Schaltplan & Firmware]] [[Category:AVR]] 075ce91df18470bb59665ea0649004f1bf5119fa 1071 1066 2016-12-31T18:08:28Z Chris 2 Beweisfotos ;) wikitext text/x-wiki Zugegeben, es hört sich nicht nur bescheuert an, es ist auch so. Trotzdem hatte ich das Bedürfnis, eine Briefkasteninnenbeleuchtung zu bauen. Warum? Nein, nicht (nur) weil ich es kann, sondern weil sie durchaus praktisch ist = Problemstellung = Die Briefkästen vom Mietshaus hier sind freistehend und in der dunklen Jahreszeit sieht man durch aufgrund der etwas ungünstig installierten Außenbeleuchtung den Einwurf nicht, ob Post gekommen ist. Durch das Öffnen der Frontklappe sieht und bekommt man zwar den Inhalt, aber dazu bin ich schlicht zu faul. Umbauten müssen rückstandsfrei sein, schließlich will ichs nicht mit meinen Vermietern verscherzen. = Idee = In den Briefkasten soll mindestens eine LED, die durch das Öffnen des Deckels aktiviert wird. Die Befestigung findet über Magnete statt, die Stromversorgung durch Batterien. Damit diese nicht unnötig leergesaugt werden, soll die Beleuchtung zeitlich begrenzt sein. = Umsetzung = Zumindest bei der LED ist die Sache schnell klar: weiße PLCC2 liegen hier mehr als genug herum. Um sie sinnvoll zu betreiben, kommen 3 Mignon-Batterien in Serie zum Einsatz. Bei 3,3 Volt (also wenn die Zellen schon halb-platt sind) sind 7 mA mehr als genug, der passende Widerstand hierfür wäre 171 Ohm. Wäre, weil ein einfacher Vorwiderstand an dieser Stelle dumm ist - die Batteriespannung wird mit dem Ladestand fallen - und damit der Strom durch die LED. == LED-Treiber == Besser ist es deshalb, eine Konstantstromquelle zu verwenden. Die lässt sich sehr einfach aufbauen, zwei Transistoren und zwei Widerstände reichen. Der Strom wird über den unteren Widerstand und Transistor definiert: letzterer wird leitend, wenn seine Basis-Emitter-Spannung über ca. 0,7 Volt steigt - diese Spannung muss beim gewünschten Strom eingeprägt werden. Für den Widerstand gilt also: :<math>\textrm{R}=\frac{0.7}{\textrm{I}_\textrm{out}}</math> Der obere Transistor steuert den Strom durch die LED. Der Widerstand dient lediglich als Pull-up und ist daher eher unkritisch. Wer ihn hinreichend groß Dimensionierung will, muss sich den LED-Strom und den Verstärkungsfaktor ansehen. Die mechanische Integration ist einfach: ich habe noch kleine Leiterkärtchen, eigentlich für einen anderen Zweck, aber es passt alles für diese Schaltung drauf. Schrumpfschlauch drüber, kleine Magnete ran, nochmal Schrumpfschlauch. <gallery> Datei:Einfacher_LED-Treiber.png|Schaltplan des einfachen LED-Treibers Datei:Briefkasten_led.jpg|Aufgebauter LED-Triber mit LED, Magnet und Schrumpfschlauch </gallery> Bilder von den Innereien gibt es leider keine. == Schalter == Für die Erkennung ob der Deckel offen ist gibt es viele Möglichkeiten: mechanischer Taster, Näherungssensoren, Neigungsschalter, Hallswitches, etc.. Mechanische Schalter brauchen in aller Regel viel Kraft (und viel Gegenkraft kann ich bei der Montage nicht bieten) und sind oft empfindlich auf Feuchte. Viele Näherungssensoren (optisch, kapazitiv und induktiv) sind aktiv und haben einen relativ großen Ruhestrom. Nichts für langen Batteriebetrieb. Neigungsschalter geht, war aber früher dank Quecksilber eine ziemliche Sauerei; die aktuellen sind wahrscheinlich besser aber ich habe Vorbehalte. Schlussendlich habe ich einen Reed-Kontakt verwendet. Hermetisch abgeschlossen, kraftfrei und kein Ruhestrom. Wenn man mechanisch faul ist oder nicht genug Grips in der Birne hat, braucht man einen Öffner - genau das (bzw. einen Wechsler) habe ich bestellt. Um die Integration vorweg zu nehmen: der Kontakt ist auf einer kleinen länglichen Leiterkarte gelandet - lang genug, um einen Magnet zur Montage am Briefkasten verwenden zu können. Jetzt kommt auch die Sache mit dem Grips: Der "Montagemagnet" war stark genug, damit das durch das Metall laufende Feld den Kontakt öffnete. Mit geschickter Positionierung beider Magnete (der zur Montage und dem im Deckel) hätte ich die Felder so ausrichten können, dass sie sich im Deckel-zu-Fall neutralisiert hätten. Hätte-hätte... Aber auch so funktioniert es. Um vor Feuchtigkeit besser geschützt zu sein, kommt alles in Schrumpfschlauch und wird natürlich auf der etwas besser geschützten Seite des Briefkastens installiert. <gallery> Datei:Briefkasten_sensor.jpg|unten: Reedschalter auf Leiterkarte mit Magnet, oben (überbelichtet): Magnet </gallery> == Abschaltautomatik == {{Infobox AVR | Typ = ATtiny13 | Takt = 0,6 | FuseH = FF | FuseL = 61 }} Eigentlich wäre diese prädestiniert für eine Analogschaltung oder einen NE555. Schlussendlich wurde es aber ein ATtiny13. Der ist mit der Aufgabe zwar gänzlich unterfordert, braucht dafür im Schlaf nahezu keinen Strom und zudem fast keine Außenbeschaltung Das Programm könnte sehr einfach sein: Port initialisieren, Pin an, warten, Pin aus. Mit 4,8 MHz Takt braucht der Controller einige Milliampere, was in beiderlei Hinsicht unnötig viel ist. Über die CLKDIV-Fuse kann der Takt auf ein Achtel reduziert werden - besser aber trotzdem nicht überragend. Was ich beim Programmieren übersehen habe: den Watchdog als Taktquelle - 128 kHz und noch etwas stromsparender. Im [http://www.atmel.com/images/doc2535.pdf Datenblatt] kann man sich dazu Figure 19-1 und 19-5 anschauen. Demnach braucht der Chip bei 600 kHz (bei externer Taktquelle) zwischen 0,3 und 0,5 mA - mit dem Watchdog wären es lediglich 0,06 bis 0,09 mA. Statt warten per Delay kann man auch den internen Timer verwenden und die CPU bei Overflow wecken. Nur leider kann man mit weiterlaufendem Takt den Tiny nicht tief genug schlafen schicken, damit es richtig gut wird. Geht man in den Tiefschlaf, bleibt der Takt komplett weg und das war dann für den Timer. Glücklicherweise kann man den Watchdog so konfigurieren, dass er keinen Reset sondern einen Interrupt auslöst. Da er einen eigenen Oszillator hat, ist er zudem unabhängig vom Systemtakt. Sein Vorteiler lässt sich bis in den angenehmen Sekundenbereich einstellen. Im Power-Down und aktivem Watchdog braucht der Prozessor (Figure 19-14) zwischen 4,5 und 7,0 µA. Nachdem das Programm durch ist und sich der Bursche schlafen legt, sinkt der Stromverbrauch (Figure 19-13) auf sehr niedrige 0,2 bis 1,2 µA. Wo liegt nochmal die Selbstentladung von Alkali-Zellen? == Batteriewächter == Darf's ein bisschen mehr sein? Der ATtiny13 hat einen ADC, warum also nicht noch zusätzlich eine Warnung für bald leere Batterien einbauen? Einige AVRs können den ADC verkehrte Welt spielen lassen: Man kann die interne Referenz als Eingang wählen und die Versorgungsspannung als Referenz. Dadurch wird das Ergebnis zwar reziprok aber die Messung braucht keine externe Beschaltung und ist zudem sehr stromsparend. Geht hier leider nicht (Figure 14-1). Es muss also ein externer Spannungsteiler her. Der braucht permanent einen gewissen Strom und das ist Mist. Man kann die Widerstände zwar nach oben dimensionieren, dann wird die Messung durch ADC-bedingte Verfälschungen ungenauer. Ich bin einen etwas faulen (im Sinne von: warum mehr Zeit verschwenden) Kompromiss eingegangen: Der Spannungsteiler wird vom Schaltsignal für die LEDs versorgt. Dadurch haut der Strom nur für die maximal 30 Sekunden ab und zugleich hat der FET einen Pull-Dowm am Gate, falls der IO doch mal floatet. Der Treiber im AVR ist einen leichten Spannungsabfall haben, aber zum einen kann man kalibrieren und zum anderen wird keine besonders hohe Genauigkeit benötigt. Bei der Dimensionierung muss man - wie bereits erwähnt - darauf achten, dass die Messung halbwegs sauber funktioniert aber gleichzeitig nicht unnötig viel Strom verbraucht wird. Natürlich muss auch der Teiler passen. Für diesen Zweck verwende ich gerne [https://www.muellerzumhagen.de/widerstand-ist-zwecklos-pointless-resistance/ Widerstand ist zwecklos], das die Paarung 33 kOhm (top) und 10 kOhm (bottom) ausspuckte. Damit ergibt sich eine maximal messbare Spannung von 4,73 V und ein Stromverbrauch von nicht ganz 105 µA bei 4,5 V. Die Auflösung wäre damit nicht ganz 4,6 mV - deutlich mehr als genug. Der ADC-Wert berechnet sich theoretisch wie folgt: :<math>\textrm{ADC}= \textrm{U}_{\textrm{bat}} \cdot \frac{10\textrm{ k}\Omega}{10\textrm{ k}\Omega+33\textrm{ k}\Omega} \cdot \frac{1024}{1.1\textrm{ V}}</math> Die Messung selbst ist geradeaus: Auswählen der Referenz und Eingang (PB4), Takt festlegen, Interrupt an und los geht's. Um etwas sinnvolles zu machen während die Messung durchgeführt wird, legt sich der Kern schlafen und wird wieder geweckt, sobald diese durch ist (sei(); nicht vergessen!). Anschließend wird der ADC-Wert ausgelesen und der Block wieder deaktiviert. Um etwas bessere Ergebnisse zu erlangen, wird die Batteriespannung nicht direkt nach dem Start sondern nach einer Sekunde durchgeführt. Dadurch lassen sich zwei Dinge verknüpfen: Die Batterien sehen eine Last und man ist am richtigen Zeitpunkt, um die LEDs kurz auszuschalten. <gallery> Datei:Briefkasten_sch1.png|Schaltung </gallery> === Kalibrierung === Aufgrund der Beschaltung sah ich mich genötigt, den ADC zu testen. Der einfachste Weg dafür wäre UART, den es aber nicht gibt. Zumindest nicht in Hardware. Das Format ist relativ einfach, siehe [[wpde:Universal_Asynchronous_Receiver_Transmitter|Wikipedia]]. Idle high, Startbit, Daten und ein bisschen Pause fürs Stopbit (die ich mir gespart hab). Mit dem Wissen, wie lange ein NOP in der CPU dauert die Timings angepasst und los geht's. Mit "normalen" USB<>UART-Adaptern hat man allerdings wenig Spaß: meine Implementierung verwendet - der Faulheit wegen - 10 Datenbits und eine ziemlich krumme Baudrate, die halt einfach gerade gepasst hat. Der Logic Analyzer kann das, die meisten Wandler aber nicht. Aber wer will schon Interoperabilität? Das Ende vom Lied: die Berechnung von oben ist hinreichend genau. == Einbau == Dank der Magnete (Sensor + LEDs) und der Gravitation (Akkus und Mikrocontroller) lässt sich alles befestigen, wo es hin soll. Die Feinausrichtung des Reed-Kontakts geht schnell und einfach. = Es geht besser = Kein Projekt würde mal zweimal genau gleich machen. So auch hier. * LED-Treiber mit FET statt Bipolar-Transistoren aufbauen und dann auch gleich den gemeinsamen FET zum Schalten der Treiber sparen, indem die Versorgung von den Transistoren direkt vom Mikrocontroller kommt. * Spannungsteiler eine Nummer größer dimensionieren und etwas mehr Ungenauigkeit (who cares?!) in Kauf nehmen. Genauso würde ich im AVR gleich den Watchdog als Taktquelle nehmen. * Als Reed-Kontakt einen Schließer nehmen, ihn durch den Befestigungsmagnet "vorspannen" und das Feld durch den Magnet im Deckel neutralisieren. Geht sicher auch auf länger gut und senkt die Bauteilkosten. * Verringern der Betriebsdauer auf 10 Sekunden. Wer starrt schon 30 Sekunden in einen Briefkastenschlitz? <gallery> Datei:Briefkasten_sch2.png|Der etwas verbesserte Schaltplan </gallery> = Unterm Strich = Es ist wirklich sehr praktisch! Die Bilder unten wurden mit gleicher Belichtungseinstellung (mit eingeschalteter Außenbeleuchtung) aufgenommen und spiegeln in etwa die menschliche Helligkeitswahrnehmung wider: <gallery> Datei:Briefkasten_geschlossen.jpg|Geschlossen Datei:Briefkasten_offen.jpg|Geöffnet Datei:Briefkasten_oben.jpg|Blick von oben (keine Post) </gallery> = Trivia = * Der Freund meiner Nachbarin hält mich jetzt wohl für wahnsinnig, weil ich minutenlang vor dem Briefkasten stand und ihn öffnete und schloss ohne ihn zu bemerken. Warum schleicht er auch so herum? * Durch die Mechanische Verkopplung kann man das Klicken des Reedkontakts tatsächlich hören. = Download = [[Datei:Briefkasten.zip|Schaltplan & Firmware]] [[Category:AVR]] 462ca521dd88b0a9bb30a617cd313d5f5eb9e3d4 Datei:Briefkasten geschlossen.jpg 6 446 1068 2016-12-31T18:04:17Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Briefkasten offen.jpg 6 447 1069 2016-12-31T18:04:26Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Briefkasten oben.jpg 6 448 1070 2016-12-31T18:04:32Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Prozeda-Decoder.zip 6 449 1072 2017-02-22T21:20:52Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 1085 1072 2017-02-22T21:29:57Z Chris 2 lud eine neue Version von „[[Datei:Prozeda-Decoder.zip]]“ hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Prozeda 11bit wtf.png 6 452 1075 2017-02-22T21:24:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Prozeda bitrate.png 6 453 1076 2017-02-22T21:24:20Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Prozeda buchse.jpg 6 454 1077 2017-02-22T21:24:46Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Prozeda Datenformat.png 6 455 1078 2017-02-22T21:25:02Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Prozeda regler.jpg 6 456 1079 2017-02-22T21:25:31Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Prozeda stick.jpg 6 457 1080 2017-02-22T21:25:47Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Prozeda verdaechtig.png 6 458 1081 2017-02-22T21:25:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Prozeda sch.png 6 459 1082 2017-02-22T21:26:22Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Prozeda-Decoder 0 460 1083 2017-02-22T21:27:33Z Chris 2 Seite erstellt wikitext text/x-wiki <nowiki><style type="text/css"> .hb1 { background-color: #C1F5C1; } .hb2 { background-color: #CDC2EF; } .hb3 { background-color: #FFF6C9; } .hb4 { background-color: #FFC9C9; } .hb5 { background-color: #BED8ED; } .hb6 { background-color: #EDBBED; } .hb7 { background-color: #F4FDC7; } .hb8 { background-color: #FFE8C9; } .hf1 { color: #66D766; } .hf2 { color: #7C67C0; } .hf3 { color: #FFE879; } .hf4 { color: #FF7979; } .hf5 { color: #5D90B7; } .hf6 { color: #B857B8; } .hf7 { color: #E2F876; } .hf8 { color: #FFC679; } </style></nowiki> [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FTDI2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <syntaxhighlight lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </syntaxhighlight> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <syntaxhighlight lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </syntaxhighlight> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <syntaxhighlight lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </syntaxhighlight> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <syntaxhighlight lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </syntaxhighlight> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <syntaxhighlight lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </syntaxhighlight> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task<code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick<code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in prozeda_tick wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Microcontrollers wurde sowohl ein anderer Microcontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. =Downloads= [[Prozeda-Decoder.zip]] Enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Category:AVR]] [[Category:Protokoll]] [[Category:Reverse Engineering]] 5ca29322ccb2276fe865136e1bcdc379431a292a 1086 1083 2017-02-22T21:30:36Z Chris 2 /* Downloads */ Link korrigiert wikitext text/x-wiki <nowiki><style type="text/css"> .hb1 { background-color: #C1F5C1; } .hb2 { background-color: #CDC2EF; } .hb3 { background-color: #FFF6C9; } .hb4 { background-color: #FFC9C9; } .hb5 { background-color: #BED8ED; } .hb6 { background-color: #EDBBED; } .hb7 { background-color: #F4FDC7; } .hb8 { background-color: #FFE8C9; } .hf1 { color: #66D766; } .hf2 { color: #7C67C0; } .hf3 { color: #FFE879; } .hf4 { color: #FF7979; } .hf5 { color: #5D90B7; } .hf6 { color: #B857B8; } .hf7 { color: #E2F876; } .hf8 { color: #FFC679; } </style></nowiki> [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FTDI2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <syntaxhighlight lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </syntaxhighlight> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <syntaxhighlight lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </syntaxhighlight> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <syntaxhighlight lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </syntaxhighlight> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <syntaxhighlight lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </syntaxhighlight> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <syntaxhighlight lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </syntaxhighlight> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task<code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick<code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in prozeda_tick wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Microcontrollers wurde sowohl ein anderer Microcontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Category:AVR]] [[Category:Protokoll]] [[Category:Reverse Engineering]] 55b7bd5987913f67a694dc0dfdb71d4992bdfee7 1087 1086 2017-02-24T19:38:02Z Chris 2 /* Anmerkungen */ Typo korrigiert wikitext text/x-wiki <nowiki><style type="text/css"> .hb1 { background-color: #C1F5C1; } .hb2 { background-color: #CDC2EF; } .hb3 { background-color: #FFF6C9; } .hb4 { background-color: #FFC9C9; } .hb5 { background-color: #BED8ED; } .hb6 { background-color: #EDBBED; } .hb7 { background-color: #F4FDC7; } .hb8 { background-color: #FFE8C9; } .hf1 { color: #66D766; } .hf2 { color: #7C67C0; } .hf3 { color: #FFE879; } .hf4 { color: #FF7979; } .hf5 { color: #5D90B7; } .hf6 { color: #B857B8; } .hf7 { color: #E2F876; } .hf8 { color: #FFC679; } </style></nowiki> [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FTDI2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <syntaxhighlight lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </syntaxhighlight> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <syntaxhighlight lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </syntaxhighlight> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <syntaxhighlight lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </syntaxhighlight> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <syntaxhighlight lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </syntaxhighlight> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <syntaxhighlight lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </syntaxhighlight> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task<code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick<code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in prozeda_tick wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Category:AVR]] [[Category:Protokoll]] [[Category:Reverse Engineering]] 63eb8042233ff514680e7e1010392079e5c48219 1090 1087 2017-02-25T15:43:26Z Chris 2 CSS geändert wikitext text/x-wiki {{#css: .hb1 { background-color: #C1F5C1; } .hb2 { background-color: #CDC2EF; } .hb3 { background-color: #FFF6C9; } .hb4 { background-color: #FFC9C9; } .hb5 { background-color: #BED8ED; } .hb6 { background-color: #EDBBED; } .hb7 { background-color: #F4FDC7; } .hb8 { background-color: #FFE8C9; } .hf1 { color: #66D766; } .hf2 { color: #7C67C0; } .hf3 { color: #FFE879; } .hf4 { color: #FF7979; } .hf5 { color: #5D90B7; } .hf6 { color: #B857B8; } .hf7 { color: #E2F876; } .hf8 { color: #FFC679; } }} [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FTDI2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <syntaxhighlight lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </syntaxhighlight> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <syntaxhighlight lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </syntaxhighlight> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <syntaxhighlight lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </syntaxhighlight> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <syntaxhighlight lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </syntaxhighlight> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <syntaxhighlight lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </syntaxhighlight> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task<code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick<code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in prozeda_tick wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Category:AVR]] [[Category:Protokoll]] [[Category:Reverse Engineering]] 3290a8714ea3ef5dc79cee227c971feab3de6156 1093 1090 2017-04-13T20:33:12Z Chris 2 syntax highlighting korrigiert wikitext text/x-wiki {{#css: .hb1 { background-color: #C1F5C1; } .hb2 { background-color: #CDC2EF; } .hb3 { background-color: #FFF6C9; } .hb4 { background-color: #FFC9C9; } .hb5 { background-color: #BED8ED; } .hb6 { background-color: #EDBBED; } .hb7 { background-color: #F4FDC7; } .hb8 { background-color: #FFE8C9; } .hf1 { color: #66D766; } .hf2 { color: #7C67C0; } .hf3 { color: #FFE879; } .hf4 { color: #FF7979; } .hf5 { color: #5D90B7; } .hf6 { color: #B857B8; } .hf7 { color: #E2F876; } .hf8 { color: #FFC679; } }} [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FTDI2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <source lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </source> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <source lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </source> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <source lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </source> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <source lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </source> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task<code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick<code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in prozeda_tick wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Category:AVR]] [[Category:Protokoll]] [[Category:Reverse Engineering]] 93330da3e8f768f1a1f5d13ceeeb1cee3b07e2b3 Prozeda-Decoder/Flashimage16 0 461 1084 2017-02-22T21:27:34Z Chris 2 Seite erstellt wikitext text/x-wiki <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX 00000070 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000080 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000090 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000000A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000000B0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000000C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000000D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000000E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000000F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000100 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000110 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000120 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000130 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000140 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000150 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000160 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000170 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000180 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000190 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000001A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000001B0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000001C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000001D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000001E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 000001F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. 00000250 20 20 53 70 65 69 63 68 65 72 20 B3 20 20 00 01 Speicher ³ .. 00000260 20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 00 01 Rücklaufanh. .. 00000270 20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 00 01 Rücklaufanh. .. 00000280 20 20 20 54 20 20 20 20 20 20 00 00 00 00 00 01 T ...... 00000290 20 20 20 54 20 20 20 20 20 20 00 00 00 00 00 01 T ...... 000002A0 50 72 69 6D E4 72 20 56 6F 72 6C 61 75 66 00 01 Primär Vorlauf.. 000002B0 20 20 4B 61 6C 74 77 61 73 73 65 72 20 20 00 01 Kaltwasser .. 000002C0 20 20 20 54 20 20 20 20 20 20 00 00 00 00 00 01 T ...... 000002D0 20 46 72 69 73 63 68 77 61 73 73 65 72 20 00 01 Frischwasser .. 000002E0 20 20 41 75 73 67 61 6E 67 20 31 20 20 20 00 0A Ausgang 1 .. 000002F0 20 20 41 75 73 67 61 6E 67 20 32 20 20 20 00 0A Ausgang 2 .. 00000300 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A Ausgang 3 .. 00000310 20 20 41 75 73 67 61 6E 67 20 34 20 20 20 00 0A Ausgang 4 .. 00000320 20 20 41 75 73 67 61 6E 67 20 35 20 20 20 00 0A Ausgang 5 .. 00000330 20 20 41 75 73 67 61 6E 67 20 36 20 20 20 00 0A Ausgang 6 .. 00000340 20 20 41 75 73 67 61 6E 67 20 37 20 20 20 00 0A Ausgang 7 .. 00000350 75 6E 75 73 65 64 00 00 00 00 00 00 00 00 00 0A unused.......... 00000360 20 20 46 65 68 6C 65 72 20 20 00 00 00 00 00 0D Fehler ...... 00000370 20 20 46 65 68 6C 65 72 20 20 00 00 00 00 00 0D Fehler ...... 00000380 20 20 46 65 68 6C 65 72 20 20 00 00 00 00 00 0E Fehler ...... 00000390 20 20 20 53 70 65 69 63 68 65 72 20 20 20 00 07 Speicher .. 000003A0 44 75 6D 6D 79 00 00 00 00 00 00 00 00 00 00 00 Dummy........... 000003B0 20 20 20 53 70 65 69 63 68 65 72 20 20 20 00 0F Speicher .. 000003C0 44 75 6D 6D 79 00 00 00 00 00 00 00 00 00 00 00 Dummy........... 000003D0 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B Funktion aktiv.. 000003E0 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B Funktion aktiv.. 000003F0 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B Funktion aktiv.. 00000400 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B Funktion aktiv.. 00000410 20 20 44 75 72 63 68 66 6C 75 73 73 20 20 00 13 Durchfluss .. 00000420 20 20 20 5A 61 70 66 75 6E 67 20 20 20 20 00 1B Zapfung .. 00000430 44 75 6D 6D 79 00 00 00 00 00 00 00 00 00 00 00 Dummy........... 00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000004A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000004B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000004C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000004D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000004E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000004F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0B ................ 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 U.d./.ëÿÊ.à.Ë.Ë. 00000510 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 Ë.Ë.x.Ô.ã....... 00000520 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 d....UU.......É. 00000530 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 ............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 U.d.0.ëÿÉ.à.ë.ë. 00000550 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 ë.ë.y.Î.Ô. ..... 00000560 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 d....UU.......É. 00000570 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 ............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 U.d.1.ìÿÈ.ß.ë.ë. 00000590 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 ë.ë.y.Ê.Ô....... 000005A0 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 d....UU.......É. 000005B0 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 ............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 U.d.2.ìÿÈ.ß..... 000005D0 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 ....y.É.Ì....... 000005E0 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 d....UU.......É. 000005F0 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 ............úÿ.. ... </pre> 571ff1e06c11b2898a5092dc7ef30fd967cfb7bc Testseite 0 2 1088 881 2017-02-24T20:16:58Z 0:0:0:0:0:0:0:1 0 wikitext text/x-wiki {{Infobox AVR | Typ = AtMega Schießmichtot | Takt = 42 | FuseH = 0xFF | FuseL = 0xFF }} :<math>\int_{0}^{42} \frac{23}{42}x^{2} dx</math> <math>\int_{0}^{42} \frac{23}{42}x^{2} dx</math> Testseite, für interne Verwendung. <source lang="php"> <?php ladida(); $var = fopen("foobar"); ?> </source> [[Datei:Xkcd.png]] [[Datei:Xkcd.png|thumb]] [[Category:Elektronik]] ef7d46bcf51c997c49dfb3d86decdd02d200eada MediaWiki:Common.css 8 141 1091 436 2017-02-25T15:54:46Z Qsysopr 1 Diskussion ausblenden css text/css /* <source lang="css"> */ /*-----------------------------------------------------------------------------------------------*/ /* ACHTUNG! Common.css enthält die gemeinsamen Skin-Anpassungen der deutschsprachigen Wikipedia */ /*---------------------------------------------------------------------------------------------*/ /* Common.css ist in drei grundlegende Abschnitte gegliedert: */ /* 1. Editierbare Seiteninhalte */ /* 2. Sonstige Anpassungen (Spezialseiten, u.a.) */ /* 3. Hauptseitenspezifisches */ /* Jede Ergänzung/Änderung muss vorher jeweils für alle Skins auf Tauglichkeit getestet werden, */ /* individuell per User.css! Ist hier erstmal geändert, dauert es dank Cache eine Weile, bis die */ /* Änderungen bei allen Nutzern sichtbar oder, bei Fehlern, korrigiert sind. */ /* +++++ 1. ANPASSUNGEN DER ANZEIGE VON EDITIERBAREN SEITENINHALTEN +++++ */ /* Personennamen in Kapitälchen: class="Person" */ .Person { display: inline; font-variant: small-caps; font-style: normal; } /* [[Wikipedia:Zitate|Zitate]] (siehe [[Vorlage:Zitat]]) */ p.Zitat { font-style: normal; margin-bottom: 0; } p.cite { margin-top: 0; padding-left: 1em; } /* [[Wikipedia:Quellenangaben|Quellenangaben]] nicht kursiv, da sie ggf. verschiedene Bestandteile enthalten */ cite { font-style: normal; } /* Stylesheet-Ergänzung zu Standard-[[Wikipedia:Navigationsleisten|Navigationsleisten]] */ div.BoxenVerschmelzen, div.NavFrame { margin: 1.5em 0 0; padding: 2px; border: 1px solid #aaaaaa; text-align: center; border-collapse: collapse; font-size: 95%; clear: both; } div.BoxenVerschmelzen div.NavFrame, div.NavFrame + div.NavFrame { margin-top: 0; } div.BoxenVerschmelzen div.NavFrame { border-style: none; border-style: hidden; } div.NavFrame + div.NavFrame { border-top-style: none; border-top-style: hidden; } div.NavPic { margin: 0; padding: 2px; float: left; } div.NavFrame div.NavHead { font-weight: bold; font-size: 100%; background-color: #efefef; } div.NavFrame p, div.NavFrame div.NavContent, div.NavFrame div.NavContent p { font-size: 100%; } div.NavEnd { margin: 0; padding: 0; line-height: 1px; clear: both; } /* Stylesheet fuer den 'Ausklappen'-Button an Navileisten, der in [[MediaWiki:Common.js]] implementiert wird */ .NavToggle { font-size: x-small; float: right; } /* Workaround für Internet Explorer 6 */ div.NavFrame, div.NavPic, .NavToggle { position: relative; } /* Stylesheet-Ergänzung zu SideBoxen (ehedem [[Wikipedia:TownBox|TownBox]]) */ div.sideBox { position: relative; float: right; background: white; margin-left: 1em; border: 1px solid gray; padding: 0.3em; width: 200px; overflow: hidden; clear: right; } div.sideBox dl { padding: 0; margin: 0 0 0.3em 0; font-size: 96%; } div.sideBox dl dt { background: none; margin: 0.4em 0 0 0; } div.sideBox dl dd { margin: 0.1em 0 0 1.1em; background-color: #f3f3f3; } /* Stylesheet-Ergänzung zu [[Wikipedia:Taxoboxen|Taxoboxen]] und [[Wikipedia:Paläoboxen|Paläoboxen]] */ table.taxobox, table.palaeobox { border-collapse: collapse; border: 1px solid gray; float: right; clear: right; margin-left: 0.5em; background-color: white; } table.taxobox th { background-color: #9bcd9b; } table.palaeobox th { background-color: #e7dcc3; } table.taxobox th, table.palaeobox th { border: solid 1px gray; text-align: center; font-weight: bold; } table.taxobox td, table.palaeobox td { vertical-align: top; } table.taxobox .Person, table.palaeobox .Person { font-style: normal; } table.taxobox div.thumb, table.taxobox div.thumb * { background-color: #f9f9f9; } table.taxobox div.thumb, table.taxobox div.thumb *, table.palaeobox div.thumb, table.palaeobox div.thumb * { margin: 0 auto; padding: 0; float: none; border: none; } table.taxobox div.magnify, table.palaeobox div.magnify { display: none; } table.taxobox tr td div.thumb div div.thumbcaption { text-align: center; } table.palaeobox tr td div.thumb div div.thumbcaption { text-align: left; } table.taxobox td.Person, table.palaeobox td.Person { text-align: center; display: block; } table.taxobox td.taxo-name, table.taxobox td.taxo-bild, table.palaeobox td.taxo-name, table.palaeobox td.taxo-bild, table.palaeobox td.taxo-zeit { text-align: center; } table.palaeobox td.taxo-ort { text-align: left; } /* aus Vorlage zur Entlastung, skinabhängigen Darstellung und Kombinierbarkeit hierher ausgelagert */ .wikitable, .prettytable { margin: 1em 1em 1em 0; background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse; } .prettytable th, .prettytable td { border: 1px #aaa solid; padding: 0.2em; } .prettytable th { text-align: center; } .prettytable caption { font-weight: bold; } /* Zebra-Tabellen */ table.wikitable.zebra tr:nth-child(even) { background: white; } .nogrid th, .nogrid td { border: none; } div.float-left, table.float-left, .float-left { float: left; clear: left; } div.float-right, table.float-right, .float-right { float: right; clear: right; margin: 1em 0 1em 1em; } div.centered, table.centered, .centered { margin-left: auto; margin-right: auto; } .toptextcells td { vertical-align: top; } /* Bitte KEINE weiteren Definitionen dieser Art für Boxen hier, das gehört in entsprechende Vorlagen! */ /* Hier 20 Mal Trivialitäten wie "text-align:center" zu definieren verlangsamt alles und ist nicht */ /* Sinn der Sache. (Und wer nicht weiß warum, hat's nicht verstanden.) */ /* Do not expand [[Wikipedia:WikiProjekt Georeferenzierung|kvaleberg.com-URLs]] for printing */ #content span.coordinates a.external.text:after, #content span.coordinates a.external.autonumber:after, #content div.coordinates a.external.text:after, #content div.coordinates a.external.autonumber:after { content: ""; } /* Do not expand URLs for printing */ #content span.plainlinks-print a.external.text:after, #content span.plainlinks-print a.external.autonumber:after, #content div.plainlinks-print a.external.text:after, #content div.plainlinks-print a.external.autonumber:after { content: ""; } /* Metadaten (bspw. [[Wikipedia:Personendaten|Personendaten]]) */ table.metadata { border: 1px solid #aaaaaa; display: none; } .metadata-label { color: #aaaaaa; } span.metadata, span.metadata-inline { display: none; } /* * Farbdefinitionen für Rahmen und Hintergründe von [[Wikipedia:Textbausteine|Textbausteinen]]. * Hier: Standardvorgaben für "dunkle Schrift auf hellem Grund". * Für Hell-auf-dunkel-Skins ([[MediaWiki:Amethyst.css|Amethyst]]) müssen dort entsprechende Definitionen * zusätzlich eingetragen werden! Anpassungen für andere Skins sind optional. * (Die Angaben der Rahmenstärke dienen der Bequemlichkeit, so dass man * für dünne Rahmen nur noch "border-style" angeben muss.) */ .rahmenfarbe1 { /* Wie Inhaltsverzeichnis */ border-color: #aaaaaa; border-width: 1px; } .rahmenfarbe2 { /* Unauffällig, geringer Kontrast */ border-color: #e9e9e9; border-width: 1px; } .rahmenfarbe3 { /* "Rot", auffällig */ border-color: #c00000; border-width: 1px; } .rahmenfarbe4 { /* Neutrale Farbe, deutlich */ border-color: #8888aa; border-width: 1px; } .rahmenfarbe5 { /* "Schwarz", hoher Kontrast */ border-color: #000000; border-width: 1px; } tr.hintergrundfarbe1 th, tr th.hintergrundfarbe1, table.hintergrundfarbe1, .hintergrundfarbe1 { /* Wie Inhaltsverzeichnis */ background-color: #f9f9f9; } tr.hintergrundfarbe2 th, tr th.hintergrundfarbe2, table.hintergrundfarbe2, .hintergrundfarbe2 { /* "Weiß", für Nicht-Artikel-Seiten, neutral */ background-color: #ffffff; } tr.hintergrundfarbe3 th, tr th.hintergrundfarbe3, table.hintergrundfarbe3, .hintergrundfarbe3 { /* "Gelb", auffällig */ background-color: #ffff40; } tr.hintergrundfarbe4 th, tr th.hintergrundfarbe4, table.hintergrundfarbe4, .hintergrundfarbe4 { /* Sehr auffällig */ background-color: #ffaa00; } tr.hintergrundfarbe5 th, tr th.hintergrundfarbe5, table.hintergrundfarbe5, .hintergrundfarbe5 { /* Neutral, abgesetzt */ background-color: #e0e0e0; } tr.hintergrundfarbe6 th, tr th.hintergrundfarbe6, table.hintergrundfarbe6, .hintergrundfarbe6 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b3b7ff; } tr.hintergrundfarbe7 th, tr th.hintergrundfarbe7, table.hintergrundfarbe7, .hintergrundfarbe7 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffcbcb; } tr.hintergrundfarbe8 th, tr th.hintergrundfarbe8, table.hintergrundfarbe8, .hintergrundfarbe8 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffebad; } tr.hintergrundfarbe9 th, tr th.hintergrundfarbe9, table.hintergrundfarbe9, .hintergrundfarbe9 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b9ffc5; } /* Keine Vergrößerung der Zeilenhöhe durch hochgestellte Zahlen der Fußnoten */ sup.reference { font-weight: 400; font-style: normal; } sup, sub { line-height: 1em; } /* Hervorhebung der angeklickten Fußnoten und der Rückverweise in blau */ ol.references > li:target, sup.reference:target { background-color: #def; } /* Hochgestellte Buchstaben in der Einzelnachweiseliste kursiv setzen */ ol.references li a[href|="#cite_ref"] { font-style: italic; } /* Inline-Verwendung der [[:Kategorie:Vorlage:Schwesterprojektverweis|Schwesterprojektverweise]] */ ol.references li div.sisterproject { display: inline !important; } /* Für <nowiki><hiero>…</hiero></nowiki> */ .mw-hierotable, .mw-hierotable th, .mw-hierotable td { border: 0; padding: 0; } /* Für [[MediaWiki:Anoneditwarning]] und weitere Hinweise, die alle untereinander stehen */ #mw-anon-edit-warning, #mw-missingsummary, #wp_talkpagetext { width: 80%; background: #d3e1f2; border: 1px solid #1a47ff; margin: 1em auto; padding: 1em; } /* Bei URLs, die auf unser Projekt und verwandte Projekte verweisen, den Pfeil ausblenden * Dieser Pfeil dient nur dazu, auf externe Ziele hinzuweisen * Auf den Einsatz der Klasse "plainlinks" kann dadurch verzichtet werden */ #content a[href^="http://de.wikipedia.org"], #content a[href^="http://toolserver.org"] { background: none !important; padding-right: 0 !important; } #content .mw-search-formheader div.search-types ul li a[href^="http://de.wikipedia.org"], #content .mw-search-formheader div.search-types ul li a[href^="http://toolserver.org"] { padding-right: 0.5em !important; } /* Falls bei der Seitenbearbeitung vergessen wurde, die Zusammenfassung auszufüllen */ .mw-summarymissed { border: 5px solid red; padding: 2px; } /* Copyrightwarnung */ #editpage-copywarn { border: solid 1px #c00000; font-size: 90%; background-color: #ffffff; } .mw-tos-summary { border: solid 1px #c00000; background-color: #ffffff; padding-left: 1em; } /* +++++ 2. SONSTIGE ANPASSUNGEN (Spezialseiten u. a.) +++++ */ /* Markierung von Redirects in [[Special:Allpages]], [[Special:Watchlist]], Kategorien */ .allpagesredirect, .watchlistredir, .redirect-in-category { font-style: italic; } /* Fettformatierung von Admin-Spezialseiten in [[Special:Specialpages]] abschalten */ .mw-specialpagerestricted strong { font-weight: normal; } /* Legende auf [[Special:Specialpages]] ebenfalls abschalten */ div.mw-specialpages-notes { display: none; } /* Größerer Abstand zwischen TOC-Nummerierung und TOC-Eintrag */ span.tocnumber { margin-right: 0.3em; } /* Skinabhängige absolute Positionierungen ausblenden */ /* Bitte [[MediaWiki Diskussion:Common.css#Absolute_Positionierungen]] beachten */ #coordinates, #coordinates_3_ObenRechts, #issnlink, #editcount, #shortcut, #artikelstadium, .topicon, #spoken-icon, #commons-icon { display: none; } /* Anpassungen für [[:Template:Link_FA]] */ /* hide the template */ #bodyContent span.FA { display: none; } /* change the bullets for links to special articles */ #p-lang li.FA { /* hier immer auch linkFA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/d/d0/Monobook-bullet-star-transparent.png"); } /* change the bullets for links to special articles */ #p-lang li.GA { /* hier immer auch linkGA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/a/a1/Monobook-bullet-star-gray.png"); } /* Verhindere, dass Infoboxen etc. in den Inhalt von Kategorien hineinragen. Das betrifft nur Kategorieseiten. */ #mw-subcategories, #mw-pages { clear: both; } /* DIVs in ImageMaps inlinen (Vorschlag von Revolus) */ .imagemap-inline div { display: inline; } /* [[Special:Hochladen]]: Warnmeldung auf bestehende Dateien, unerwünschte Prefixe usw. deutlicher hervorheben. */ #wpDestFile-warning ul { border: solid red 1px; padding: 1.5em; } /* Warnmeldung für gesperrte Titel */ .mw-titleprotectedwarning { background-color: #eee; border: 2px solid red; padding: 1em; } /* Warnmeldung bei der Bearbeitung von Seiten im MediaWiki-Namensraum */ .mw-editinginterface { background-color: #f9f9f9; border-color: #c00000; border-width: 1px; border-style: solid; padding: 2px; } /* Überschrift 5. und 6. Ordnung proportionaler zu Fließtext */ #content h5 { font-size: 108%; /* Original: 116% */ } #content h6 { font-size: 100%; /* Original: 80% = kleiner als Bodytext, unschön */ } #content h6 .editsection { font-size: 120%; font-weight: normal; } /* Anleitung auf Special:Search */ .mw-searchresult { font-size: 84%; margin: 5px; } /* Gestaltung der Edittools-Leiste */ #specialchars { margin-top: 3px; border: solid 1px #aaaaaa; padding: 1px; text-align: left; background-color: white; } /* Legende für Versionsgeschichte */ .mw-history-legend { font-size: 90%; margin-top: 2px; margin-bottom: 2px; border: solid 1px #e9e9e9; padding: 0 5px 5px 5px; background-color: #f9f9f9; clear: both; } /* +++++ 3. NEUE [[Wikipedia:Hauptseite|HAUPTSEITE]] (ab 2006) +++++ */ /* Kategorie verbergen */ /* Überschrift verbergen */ /* Redirhinweis verbergen - ACHTUNG: Je nach Skin muss jetzt der Abstand zum oberen Rand korrigiert werden */ body.page-Wikipedia_Hauptseite #catlinks, body.page-Wikipedia_Hauptseite h1.firstHeading, body.page-Wikipedia_Hauptseite #contentSub { display: none; } #hauptseite h2 { background-color: #d8e8ff; border: 1px solid #8898bf; font-size: 1em; font-weight: bold; margin-top: 0; margin-bottom: 0; padding-top: 0.1em; padding-bottom: 0.1em; } #hauptseite .inhalt { background-color: #ffffff; border: 1px solid #8898bf; border-top: 0 solid white; padding: 0.3em 0.8em 0.4em 0.8em; } #hauptseite .inhalt hr { background-color: #8898bf; color: #8898bf; height: 1px; margin: 0.5em 0; padding: 0; } #hauptseite .inhalt .mehr { clear: both; font-size: 95%; margin-top: 0.8em; text-align: right; } #hauptseite table { background-color: transparent; } .hauptseite-oben, .hauptseite-links, .hauptseite-rechts { margin-bottom: 1em; } .hauptseite-links { margin-right: 0.5em; } .hauptseite-rechts { margin-left: 0.5em; } .hauptseite-oben h2, .hauptseite-unten h2 { text-align: center; } .hauptseite-oben .inhalt .portale { font-weight: bold; margin-top: 0.2em; margin-bottom: 0.2em; } .hauptseite-oben .inhalt .intern { font-size: 90%; text-align: center; } .hauptseite-links h2, .hauptseite-rechts h2 { text-indent: 0.8em; } #hauptseite-schwesterprojekte .inhalt a { font-weight: bold; } /* IPA links nicht unterstreichen */ .IPA a:link, .IPA a:visited { text-decoration: none; } /* CSS-Klassen für Schriftarten als Workaround für Defizite in alten IE-Versionen. * Achtung: IE6 mag keine Zeilenumbrüche zwischen den Fonts. * In IE8 nicht mehr nötig, soll mit den alten Versionen aussterben. Browserweiche: * http://www.dynamicsitesolutions.com/css/filters/star-html/ * http://www.dynamicsitesolutions.com/css/filters/first-child-plus-html/ */ * html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } *:first-child+html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } * html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } *:first-child+html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } * html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } *:first-child+html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } * html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } *:first-child+html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } * html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } *:first-child+html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } * html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } *:first-child+html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } * html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } *:first-child+html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } * html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } *:first-child+html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } * html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } *:first-child+html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } /* Standardmäßige Ausblendung der Flagged-Revisions-Backlog-Sitenotice */ #mw-oldreviewed-notice { display: none; } /* Standardmäßige Ausblendung der Flagged-Revisions-Kommentarbox */ #mw-commentbox { display: none; } /* Abstand zwischen Liste und Inhaltsverzeichnis erhöhen, siehe http://de.wikipedia.org/w/index.php?title=MediaWiki_Diskussion:Common.css&oldid=51639015#Abstand_vor_Inhaltsverzeichnis */ ul + .toc, ol + .toc { margin-top: 0.5em; } /* höheres Uploadfeld */ #wpUploadDescription { height: 20em; } /* Im Projekt WP:GEO benutzt die [[Vorlage:Coordinate]] das «geo-microformat» zur semantischen Auszeichnung des Texts. Der Inhalt dieses [[Tag (Informatik)|Tags]] ist nicht für den Leser bestimmt. */ .geo { display: none; } /* Patrollink ausblenden, da die Eweiterung hier nicht aktiviert ist und deren Optik zu sehr den gesichteten Versionen ähnelt. */ .fr-diff-patrollink, .patrollink { display: none; } /* Rollback-Knopf auf Beobachtungsliste ausblenden, da es dort nur von sehr beschränktem Nutzen ist und zu sehr vielen Reverts aus Versehen führt */ .page-Spezial_Beobachtungsliste .mw-rollback-link { display: none; } /* </source> */ /* Disable Discussion-tab */ #ca-talk { display: none; } 693ce58b0cceef7c58b4249abfca23080f6a7bfb 1092 1091 2017-04-11T18:50:33Z Qsysopr 1 reset code style css text/css /* <source lang="css"> */ /*-----------------------------------------------------------------------------------------------*/ /* ACHTUNG! Common.css enthält die gemeinsamen Skin-Anpassungen der deutschsprachigen Wikipedia */ /*---------------------------------------------------------------------------------------------*/ /* Common.css ist in drei grundlegende Abschnitte gegliedert: */ /* 1. Editierbare Seiteninhalte */ /* 2. Sonstige Anpassungen (Spezialseiten, u.a.) */ /* 3. Hauptseitenspezifisches */ /* Jede Ergänzung/Änderung muss vorher jeweils für alle Skins auf Tauglichkeit getestet werden, */ /* individuell per User.css! Ist hier erstmal geändert, dauert es dank Cache eine Weile, bis die */ /* Änderungen bei allen Nutzern sichtbar oder, bei Fehlern, korrigiert sind. */ /* +++++ 1. ANPASSUNGEN DER ANZEIGE VON EDITIERBAREN SEITENINHALTEN +++++ */ /* Personennamen in Kapitälchen: class="Person" */ .Person { display: inline; font-variant: small-caps; font-style: normal; } /* [[Wikipedia:Zitate|Zitate]] (siehe [[Vorlage:Zitat]]) */ p.Zitat { font-style: normal; margin-bottom: 0; } p.cite { margin-top: 0; padding-left: 1em; } /* [[Wikipedia:Quellenangaben|Quellenangaben]] nicht kursiv, da sie ggf. verschiedene Bestandteile enthalten */ cite { font-style: normal; } /* Stylesheet-Ergänzung zu Standard-[[Wikipedia:Navigationsleisten|Navigationsleisten]] */ div.BoxenVerschmelzen, div.NavFrame { margin: 1.5em 0 0; padding: 2px; border: 1px solid #aaaaaa; text-align: center; border-collapse: collapse; font-size: 95%; clear: both; } div.BoxenVerschmelzen div.NavFrame, div.NavFrame + div.NavFrame { margin-top: 0; } div.BoxenVerschmelzen div.NavFrame { border-style: none; border-style: hidden; } div.NavFrame + div.NavFrame { border-top-style: none; border-top-style: hidden; } div.NavPic { margin: 0; padding: 2px; float: left; } div.NavFrame div.NavHead { font-weight: bold; font-size: 100%; background-color: #efefef; } div.NavFrame p, div.NavFrame div.NavContent, div.NavFrame div.NavContent p { font-size: 100%; } div.NavEnd { margin: 0; padding: 0; line-height: 1px; clear: both; } /* Stylesheet fuer den 'Ausklappen'-Button an Navileisten, der in [[MediaWiki:Common.js]] implementiert wird */ .NavToggle { font-size: x-small; float: right; } /* Workaround für Internet Explorer 6 */ div.NavFrame, div.NavPic, .NavToggle { position: relative; } /* Stylesheet-Ergänzung zu SideBoxen (ehedem [[Wikipedia:TownBox|TownBox]]) */ div.sideBox { position: relative; float: right; background: white; margin-left: 1em; border: 1px solid gray; padding: 0.3em; width: 200px; overflow: hidden; clear: right; } div.sideBox dl { padding: 0; margin: 0 0 0.3em 0; font-size: 96%; } div.sideBox dl dt { background: none; margin: 0.4em 0 0 0; } div.sideBox dl dd { margin: 0.1em 0 0 1.1em; background-color: #f3f3f3; } /* Stylesheet-Ergänzung zu [[Wikipedia:Taxoboxen|Taxoboxen]] und [[Wikipedia:Paläoboxen|Paläoboxen]] */ table.taxobox, table.palaeobox { border-collapse: collapse; border: 1px solid gray; float: right; clear: right; margin-left: 0.5em; background-color: white; } table.taxobox th { background-color: #9bcd9b; } table.palaeobox th { background-color: #e7dcc3; } table.taxobox th, table.palaeobox th { border: solid 1px gray; text-align: center; font-weight: bold; } table.taxobox td, table.palaeobox td { vertical-align: top; } table.taxobox .Person, table.palaeobox .Person { font-style: normal; } table.taxobox div.thumb, table.taxobox div.thumb * { background-color: #f9f9f9; } table.taxobox div.thumb, table.taxobox div.thumb *, table.palaeobox div.thumb, table.palaeobox div.thumb * { margin: 0 auto; padding: 0; float: none; border: none; } table.taxobox div.magnify, table.palaeobox div.magnify { display: none; } table.taxobox tr td div.thumb div div.thumbcaption { text-align: center; } table.palaeobox tr td div.thumb div div.thumbcaption { text-align: left; } table.taxobox td.Person, table.palaeobox td.Person { text-align: center; display: block; } table.taxobox td.taxo-name, table.taxobox td.taxo-bild, table.palaeobox td.taxo-name, table.palaeobox td.taxo-bild, table.palaeobox td.taxo-zeit { text-align: center; } table.palaeobox td.taxo-ort { text-align: left; } /* aus Vorlage zur Entlastung, skinabhängigen Darstellung und Kombinierbarkeit hierher ausgelagert */ .wikitable, .prettytable { margin: 1em 1em 1em 0; background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse; } .prettytable th, .prettytable td { border: 1px #aaa solid; padding: 0.2em; } .prettytable th { text-align: center; } .prettytable caption { font-weight: bold; } /* Zebra-Tabellen */ table.wikitable.zebra tr:nth-child(even) { background: white; } .nogrid th, .nogrid td { border: none; } div.float-left, table.float-left, .float-left { float: left; clear: left; } div.float-right, table.float-right, .float-right { float: right; clear: right; margin: 1em 0 1em 1em; } div.centered, table.centered, .centered { margin-left: auto; margin-right: auto; } .toptextcells td { vertical-align: top; } /* Bitte KEINE weiteren Definitionen dieser Art für Boxen hier, das gehört in entsprechende Vorlagen! */ /* Hier 20 Mal Trivialitäten wie "text-align:center" zu definieren verlangsamt alles und ist nicht */ /* Sinn der Sache. (Und wer nicht weiß warum, hat's nicht verstanden.) */ /* Do not expand [[Wikipedia:WikiProjekt Georeferenzierung|kvaleberg.com-URLs]] for printing */ #content span.coordinates a.external.text:after, #content span.coordinates a.external.autonumber:after, #content div.coordinates a.external.text:after, #content div.coordinates a.external.autonumber:after { content: ""; } /* Do not expand URLs for printing */ #content span.plainlinks-print a.external.text:after, #content span.plainlinks-print a.external.autonumber:after, #content div.plainlinks-print a.external.text:after, #content div.plainlinks-print a.external.autonumber:after { content: ""; } /* Metadaten (bspw. [[Wikipedia:Personendaten|Personendaten]]) */ table.metadata { border: 1px solid #aaaaaa; display: none; } .metadata-label { color: #aaaaaa; } span.metadata, span.metadata-inline { display: none; } /* * Farbdefinitionen für Rahmen und Hintergründe von [[Wikipedia:Textbausteine|Textbausteinen]]. * Hier: Standardvorgaben für "dunkle Schrift auf hellem Grund". * Für Hell-auf-dunkel-Skins ([[MediaWiki:Amethyst.css|Amethyst]]) müssen dort entsprechende Definitionen * zusätzlich eingetragen werden! Anpassungen für andere Skins sind optional. * (Die Angaben der Rahmenstärke dienen der Bequemlichkeit, so dass man * für dünne Rahmen nur noch "border-style" angeben muss.) */ .rahmenfarbe1 { /* Wie Inhaltsverzeichnis */ border-color: #aaaaaa; border-width: 1px; } .rahmenfarbe2 { /* Unauffällig, geringer Kontrast */ border-color: #e9e9e9; border-width: 1px; } .rahmenfarbe3 { /* "Rot", auffällig */ border-color: #c00000; border-width: 1px; } .rahmenfarbe4 { /* Neutrale Farbe, deutlich */ border-color: #8888aa; border-width: 1px; } .rahmenfarbe5 { /* "Schwarz", hoher Kontrast */ border-color: #000000; border-width: 1px; } tr.hintergrundfarbe1 th, tr th.hintergrundfarbe1, table.hintergrundfarbe1, .hintergrundfarbe1 { /* Wie Inhaltsverzeichnis */ background-color: #f9f9f9; } tr.hintergrundfarbe2 th, tr th.hintergrundfarbe2, table.hintergrundfarbe2, .hintergrundfarbe2 { /* "Weiß", für Nicht-Artikel-Seiten, neutral */ background-color: #ffffff; } tr.hintergrundfarbe3 th, tr th.hintergrundfarbe3, table.hintergrundfarbe3, .hintergrundfarbe3 { /* "Gelb", auffällig */ background-color: #ffff40; } tr.hintergrundfarbe4 th, tr th.hintergrundfarbe4, table.hintergrundfarbe4, .hintergrundfarbe4 { /* Sehr auffällig */ background-color: #ffaa00; } tr.hintergrundfarbe5 th, tr th.hintergrundfarbe5, table.hintergrundfarbe5, .hintergrundfarbe5 { /* Neutral, abgesetzt */ background-color: #e0e0e0; } tr.hintergrundfarbe6 th, tr th.hintergrundfarbe6, table.hintergrundfarbe6, .hintergrundfarbe6 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b3b7ff; } tr.hintergrundfarbe7 th, tr th.hintergrundfarbe7, table.hintergrundfarbe7, .hintergrundfarbe7 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffcbcb; } tr.hintergrundfarbe8 th, tr th.hintergrundfarbe8, table.hintergrundfarbe8, .hintergrundfarbe8 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffebad; } tr.hintergrundfarbe9 th, tr th.hintergrundfarbe9, table.hintergrundfarbe9, .hintergrundfarbe9 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b9ffc5; } /* Keine Vergrößerung der Zeilenhöhe durch hochgestellte Zahlen der Fußnoten */ sup.reference { font-weight: 400; font-style: normal; } sup, sub { line-height: 1em; } /* Hervorhebung der angeklickten Fußnoten und der Rückverweise in blau */ ol.references > li:target, sup.reference:target { background-color: #def; } /* Hochgestellte Buchstaben in der Einzelnachweiseliste kursiv setzen */ ol.references li a[href|="#cite_ref"] { font-style: italic; } /* Inline-Verwendung der [[:Kategorie:Vorlage:Schwesterprojektverweis|Schwesterprojektverweise]] */ ol.references li div.sisterproject { display: inline !important; } /* Für <nowiki><hiero>…</hiero></nowiki> */ .mw-hierotable, .mw-hierotable th, .mw-hierotable td { border: 0; padding: 0; } /* Für [[MediaWiki:Anoneditwarning]] und weitere Hinweise, die alle untereinander stehen */ #mw-anon-edit-warning, #mw-missingsummary, #wp_talkpagetext { width: 80%; background: #d3e1f2; border: 1px solid #1a47ff; margin: 1em auto; padding: 1em; } /* Bei URLs, die auf unser Projekt und verwandte Projekte verweisen, den Pfeil ausblenden * Dieser Pfeil dient nur dazu, auf externe Ziele hinzuweisen * Auf den Einsatz der Klasse "plainlinks" kann dadurch verzichtet werden */ #content a[href^="http://de.wikipedia.org"], #content a[href^="http://toolserver.org"] { background: none !important; padding-right: 0 !important; } #content .mw-search-formheader div.search-types ul li a[href^="http://de.wikipedia.org"], #content .mw-search-formheader div.search-types ul li a[href^="http://toolserver.org"] { padding-right: 0.5em !important; } /* Falls bei der Seitenbearbeitung vergessen wurde, die Zusammenfassung auszufüllen */ .mw-summarymissed { border: 5px solid red; padding: 2px; } /* Copyrightwarnung */ #editpage-copywarn { border: solid 1px #c00000; font-size: 90%; background-color: #ffffff; } .mw-tos-summary { border: solid 1px #c00000; background-color: #ffffff; padding-left: 1em; } /* +++++ 2. SONSTIGE ANPASSUNGEN (Spezialseiten u. a.) +++++ */ /* Markierung von Redirects in [[Special:Allpages]], [[Special:Watchlist]], Kategorien */ .allpagesredirect, .watchlistredir, .redirect-in-category { font-style: italic; } /* Fettformatierung von Admin-Spezialseiten in [[Special:Specialpages]] abschalten */ .mw-specialpagerestricted strong { font-weight: normal; } /* Legende auf [[Special:Specialpages]] ebenfalls abschalten */ div.mw-specialpages-notes { display: none; } /* Größerer Abstand zwischen TOC-Nummerierung und TOC-Eintrag */ span.tocnumber { margin-right: 0.3em; } /* Skinabhängige absolute Positionierungen ausblenden */ /* Bitte [[MediaWiki Diskussion:Common.css#Absolute_Positionierungen]] beachten */ #coordinates, #coordinates_3_ObenRechts, #issnlink, #editcount, #shortcut, #artikelstadium, .topicon, #spoken-icon, #commons-icon { display: none; } /* Anpassungen für [[:Template:Link_FA]] */ /* hide the template */ #bodyContent span.FA { display: none; } /* change the bullets for links to special articles */ #p-lang li.FA { /* hier immer auch linkFA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/d/d0/Monobook-bullet-star-transparent.png"); } /* change the bullets for links to special articles */ #p-lang li.GA { /* hier immer auch linkGA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/a/a1/Monobook-bullet-star-gray.png"); } /* Verhindere, dass Infoboxen etc. in den Inhalt von Kategorien hineinragen. Das betrifft nur Kategorieseiten. */ #mw-subcategories, #mw-pages { clear: both; } /* DIVs in ImageMaps inlinen (Vorschlag von Revolus) */ .imagemap-inline div { display: inline; } /* [[Special:Hochladen]]: Warnmeldung auf bestehende Dateien, unerwünschte Prefixe usw. deutlicher hervorheben. */ #wpDestFile-warning ul { border: solid red 1px; padding: 1.5em; } /* Warnmeldung für gesperrte Titel */ .mw-titleprotectedwarning { background-color: #eee; border: 2px solid red; padding: 1em; } /* Warnmeldung bei der Bearbeitung von Seiten im MediaWiki-Namensraum */ .mw-editinginterface { background-color: #f9f9f9; border-color: #c00000; border-width: 1px; border-style: solid; padding: 2px; } /* Überschrift 5. und 6. Ordnung proportionaler zu Fließtext */ #content h5 { font-size: 108%; /* Original: 116% */ } #content h6 { font-size: 100%; /* Original: 80% = kleiner als Bodytext, unschön */ } #content h6 .editsection { font-size: 120%; font-weight: normal; } /* Anleitung auf Special:Search */ .mw-searchresult { font-size: 84%; margin: 5px; } /* Gestaltung der Edittools-Leiste */ #specialchars { margin-top: 3px; border: solid 1px #aaaaaa; padding: 1px; text-align: left; background-color: white; } /* Legende für Versionsgeschichte */ .mw-history-legend { font-size: 90%; margin-top: 2px; margin-bottom: 2px; border: solid 1px #e9e9e9; padding: 0 5px 5px 5px; background-color: #f9f9f9; clear: both; } /* +++++ 3. NEUE [[Wikipedia:Hauptseite|HAUPTSEITE]] (ab 2006) +++++ */ /* Kategorie verbergen */ /* Überschrift verbergen */ /* Redirhinweis verbergen - ACHTUNG: Je nach Skin muss jetzt der Abstand zum oberen Rand korrigiert werden */ body.page-Wikipedia_Hauptseite #catlinks, body.page-Wikipedia_Hauptseite h1.firstHeading, body.page-Wikipedia_Hauptseite #contentSub { display: none; } #hauptseite h2 { background-color: #d8e8ff; border: 1px solid #8898bf; font-size: 1em; font-weight: bold; margin-top: 0; margin-bottom: 0; padding-top: 0.1em; padding-bottom: 0.1em; } #hauptseite .inhalt { background-color: #ffffff; border: 1px solid #8898bf; border-top: 0 solid white; padding: 0.3em 0.8em 0.4em 0.8em; } #hauptseite .inhalt hr { background-color: #8898bf; color: #8898bf; height: 1px; margin: 0.5em 0; padding: 0; } #hauptseite .inhalt .mehr { clear: both; font-size: 95%; margin-top: 0.8em; text-align: right; } #hauptseite table { background-color: transparent; } .hauptseite-oben, .hauptseite-links, .hauptseite-rechts { margin-bottom: 1em; } .hauptseite-links { margin-right: 0.5em; } .hauptseite-rechts { margin-left: 0.5em; } .hauptseite-oben h2, .hauptseite-unten h2 { text-align: center; } .hauptseite-oben .inhalt .portale { font-weight: bold; margin-top: 0.2em; margin-bottom: 0.2em; } .hauptseite-oben .inhalt .intern { font-size: 90%; text-align: center; } .hauptseite-links h2, .hauptseite-rechts h2 { text-indent: 0.8em; } #hauptseite-schwesterprojekte .inhalt a { font-weight: bold; } /* IPA links nicht unterstreichen */ .IPA a:link, .IPA a:visited { text-decoration: none; } /* CSS-Klassen für Schriftarten als Workaround für Defizite in alten IE-Versionen. * Achtung: IE6 mag keine Zeilenumbrüche zwischen den Fonts. * In IE8 nicht mehr nötig, soll mit den alten Versionen aussterben. Browserweiche: * http://www.dynamicsitesolutions.com/css/filters/star-html/ * http://www.dynamicsitesolutions.com/css/filters/first-child-plus-html/ */ * html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } *:first-child+html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } * html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } *:first-child+html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } * html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } *:first-child+html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } * html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } *:first-child+html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } * html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } *:first-child+html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } * html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } *:first-child+html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } * html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } *:first-child+html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } * html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } *:first-child+html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } * html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } *:first-child+html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } /* Standardmäßige Ausblendung der Flagged-Revisions-Backlog-Sitenotice */ #mw-oldreviewed-notice { display: none; } /* Standardmäßige Ausblendung der Flagged-Revisions-Kommentarbox */ #mw-commentbox { display: none; } /* Abstand zwischen Liste und Inhaltsverzeichnis erhöhen, siehe http://de.wikipedia.org/w/index.php?title=MediaWiki_Diskussion:Common.css&oldid=51639015#Abstand_vor_Inhaltsverzeichnis */ ul + .toc, ol + .toc { margin-top: 0.5em; } /* höheres Uploadfeld */ #wpUploadDescription { height: 20em; } /* Im Projekt WP:GEO benutzt die [[Vorlage:Coordinate]] das «geo-microformat» zur semantischen Auszeichnung des Texts. Der Inhalt dieses [[Tag (Informatik)|Tags]] ist nicht für den Leser bestimmt. */ .geo { display: none; } /* Patrollink ausblenden, da die Eweiterung hier nicht aktiviert ist und deren Optik zu sehr den gesichteten Versionen ähnelt. */ .fr-diff-patrollink, .patrollink { display: none; } /* Rollback-Knopf auf Beobachtungsliste ausblenden, da es dort nur von sehr beschränktem Nutzen ist und zu sehr vielen Reverts aus Versehen führt */ .page-Spezial_Beobachtungsliste .mw-rollback-link { display: none; } /* </source> */ /* Disable Discussion-tab */ #ca-talk { display: none; } /* reset code style */ code { background-color: none !important; border: none !important; border-radius: 0; padding: 0; } 0bfbf285121b4789ab66d43d85c2ca1bfa78f893 1095 1092 2017-04-15T16:43:51Z Qsysopr 1 Keine Zeilenumbrüche in pre-Tags css text/css /* <source lang="css"> */ /*-----------------------------------------------------------------------------------------------*/ /* ACHTUNG! Common.css enthält die gemeinsamen Skin-Anpassungen der deutschsprachigen Wikipedia */ /*---------------------------------------------------------------------------------------------*/ /* Common.css ist in drei grundlegende Abschnitte gegliedert: */ /* 1. Editierbare Seiteninhalte */ /* 2. Sonstige Anpassungen (Spezialseiten, u.a.) */ /* 3. Hauptseitenspezifisches */ /* Jede Ergänzung/Änderung muss vorher jeweils für alle Skins auf Tauglichkeit getestet werden, */ /* individuell per User.css! Ist hier erstmal geändert, dauert es dank Cache eine Weile, bis die */ /* Änderungen bei allen Nutzern sichtbar oder, bei Fehlern, korrigiert sind. */ /* +++++ 1. ANPASSUNGEN DER ANZEIGE VON EDITIERBAREN SEITENINHALTEN +++++ */ /* Personennamen in Kapitälchen: class="Person" */ .Person { display: inline; font-variant: small-caps; font-style: normal; } /* [[Wikipedia:Zitate|Zitate]] (siehe [[Vorlage:Zitat]]) */ p.Zitat { font-style: normal; margin-bottom: 0; } p.cite { margin-top: 0; padding-left: 1em; } /* [[Wikipedia:Quellenangaben|Quellenangaben]] nicht kursiv, da sie ggf. verschiedene Bestandteile enthalten */ cite { font-style: normal; } /* Stylesheet-Ergänzung zu Standard-[[Wikipedia:Navigationsleisten|Navigationsleisten]] */ div.BoxenVerschmelzen, div.NavFrame { margin: 1.5em 0 0; padding: 2px; border: 1px solid #aaaaaa; text-align: center; border-collapse: collapse; font-size: 95%; clear: both; } div.BoxenVerschmelzen div.NavFrame, div.NavFrame + div.NavFrame { margin-top: 0; } div.BoxenVerschmelzen div.NavFrame { border-style: none; border-style: hidden; } div.NavFrame + div.NavFrame { border-top-style: none; border-top-style: hidden; } div.NavPic { margin: 0; padding: 2px; float: left; } div.NavFrame div.NavHead { font-weight: bold; font-size: 100%; background-color: #efefef; } div.NavFrame p, div.NavFrame div.NavContent, div.NavFrame div.NavContent p { font-size: 100%; } div.NavEnd { margin: 0; padding: 0; line-height: 1px; clear: both; } /* Stylesheet fuer den 'Ausklappen'-Button an Navileisten, der in [[MediaWiki:Common.js]] implementiert wird */ .NavToggle { font-size: x-small; float: right; } /* Workaround für Internet Explorer 6 */ div.NavFrame, div.NavPic, .NavToggle { position: relative; } /* Stylesheet-Ergänzung zu SideBoxen (ehedem [[Wikipedia:TownBox|TownBox]]) */ div.sideBox { position: relative; float: right; background: white; margin-left: 1em; border: 1px solid gray; padding: 0.3em; width: 200px; overflow: hidden; clear: right; } div.sideBox dl { padding: 0; margin: 0 0 0.3em 0; font-size: 96%; } div.sideBox dl dt { background: none; margin: 0.4em 0 0 0; } div.sideBox dl dd { margin: 0.1em 0 0 1.1em; background-color: #f3f3f3; } /* Stylesheet-Ergänzung zu [[Wikipedia:Taxoboxen|Taxoboxen]] und [[Wikipedia:Paläoboxen|Paläoboxen]] */ table.taxobox, table.palaeobox { border-collapse: collapse; border: 1px solid gray; float: right; clear: right; margin-left: 0.5em; background-color: white; } table.taxobox th { background-color: #9bcd9b; } table.palaeobox th { background-color: #e7dcc3; } table.taxobox th, table.palaeobox th { border: solid 1px gray; text-align: center; font-weight: bold; } table.taxobox td, table.palaeobox td { vertical-align: top; } table.taxobox .Person, table.palaeobox .Person { font-style: normal; } table.taxobox div.thumb, table.taxobox div.thumb * { background-color: #f9f9f9; } table.taxobox div.thumb, table.taxobox div.thumb *, table.palaeobox div.thumb, table.palaeobox div.thumb * { margin: 0 auto; padding: 0; float: none; border: none; } table.taxobox div.magnify, table.palaeobox div.magnify { display: none; } table.taxobox tr td div.thumb div div.thumbcaption { text-align: center; } table.palaeobox tr td div.thumb div div.thumbcaption { text-align: left; } table.taxobox td.Person, table.palaeobox td.Person { text-align: center; display: block; } table.taxobox td.taxo-name, table.taxobox td.taxo-bild, table.palaeobox td.taxo-name, table.palaeobox td.taxo-bild, table.palaeobox td.taxo-zeit { text-align: center; } table.palaeobox td.taxo-ort { text-align: left; } /* aus Vorlage zur Entlastung, skinabhängigen Darstellung und Kombinierbarkeit hierher ausgelagert */ .wikitable, .prettytable { margin: 1em 1em 1em 0; background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse; } .prettytable th, .prettytable td { border: 1px #aaa solid; padding: 0.2em; } .prettytable th { text-align: center; } .prettytable caption { font-weight: bold; } /* Zebra-Tabellen */ table.wikitable.zebra tr:nth-child(even) { background: white; } .nogrid th, .nogrid td { border: none; } div.float-left, table.float-left, .float-left { float: left; clear: left; } div.float-right, table.float-right, .float-right { float: right; clear: right; margin: 1em 0 1em 1em; } div.centered, table.centered, .centered { margin-left: auto; margin-right: auto; } .toptextcells td { vertical-align: top; } /* Bitte KEINE weiteren Definitionen dieser Art für Boxen hier, das gehört in entsprechende Vorlagen! */ /* Hier 20 Mal Trivialitäten wie "text-align:center" zu definieren verlangsamt alles und ist nicht */ /* Sinn der Sache. (Und wer nicht weiß warum, hat's nicht verstanden.) */ /* Do not expand [[Wikipedia:WikiProjekt Georeferenzierung|kvaleberg.com-URLs]] for printing */ #content span.coordinates a.external.text:after, #content span.coordinates a.external.autonumber:after, #content div.coordinates a.external.text:after, #content div.coordinates a.external.autonumber:after { content: ""; } /* Do not expand URLs for printing */ #content span.plainlinks-print a.external.text:after, #content span.plainlinks-print a.external.autonumber:after, #content div.plainlinks-print a.external.text:after, #content div.plainlinks-print a.external.autonumber:after { content: ""; } /* Metadaten (bspw. [[Wikipedia:Personendaten|Personendaten]]) */ table.metadata { border: 1px solid #aaaaaa; display: none; } .metadata-label { color: #aaaaaa; } span.metadata, span.metadata-inline { display: none; } /* * Farbdefinitionen für Rahmen und Hintergründe von [[Wikipedia:Textbausteine|Textbausteinen]]. * Hier: Standardvorgaben für "dunkle Schrift auf hellem Grund". * Für Hell-auf-dunkel-Skins ([[MediaWiki:Amethyst.css|Amethyst]]) müssen dort entsprechende Definitionen * zusätzlich eingetragen werden! Anpassungen für andere Skins sind optional. * (Die Angaben der Rahmenstärke dienen der Bequemlichkeit, so dass man * für dünne Rahmen nur noch "border-style" angeben muss.) */ .rahmenfarbe1 { /* Wie Inhaltsverzeichnis */ border-color: #aaaaaa; border-width: 1px; } .rahmenfarbe2 { /* Unauffällig, geringer Kontrast */ border-color: #e9e9e9; border-width: 1px; } .rahmenfarbe3 { /* "Rot", auffällig */ border-color: #c00000; border-width: 1px; } .rahmenfarbe4 { /* Neutrale Farbe, deutlich */ border-color: #8888aa; border-width: 1px; } .rahmenfarbe5 { /* "Schwarz", hoher Kontrast */ border-color: #000000; border-width: 1px; } tr.hintergrundfarbe1 th, tr th.hintergrundfarbe1, table.hintergrundfarbe1, .hintergrundfarbe1 { /* Wie Inhaltsverzeichnis */ background-color: #f9f9f9; } tr.hintergrundfarbe2 th, tr th.hintergrundfarbe2, table.hintergrundfarbe2, .hintergrundfarbe2 { /* "Weiß", für Nicht-Artikel-Seiten, neutral */ background-color: #ffffff; } tr.hintergrundfarbe3 th, tr th.hintergrundfarbe3, table.hintergrundfarbe3, .hintergrundfarbe3 { /* "Gelb", auffällig */ background-color: #ffff40; } tr.hintergrundfarbe4 th, tr th.hintergrundfarbe4, table.hintergrundfarbe4, .hintergrundfarbe4 { /* Sehr auffällig */ background-color: #ffaa00; } tr.hintergrundfarbe5 th, tr th.hintergrundfarbe5, table.hintergrundfarbe5, .hintergrundfarbe5 { /* Neutral, abgesetzt */ background-color: #e0e0e0; } tr.hintergrundfarbe6 th, tr th.hintergrundfarbe6, table.hintergrundfarbe6, .hintergrundfarbe6 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b3b7ff; } tr.hintergrundfarbe7 th, tr th.hintergrundfarbe7, table.hintergrundfarbe7, .hintergrundfarbe7 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffcbcb; } tr.hintergrundfarbe8 th, tr th.hintergrundfarbe8, table.hintergrundfarbe8, .hintergrundfarbe8 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffebad; } tr.hintergrundfarbe9 th, tr th.hintergrundfarbe9, table.hintergrundfarbe9, .hintergrundfarbe9 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b9ffc5; } /* Keine Vergrößerung der Zeilenhöhe durch hochgestellte Zahlen der Fußnoten */ sup.reference { font-weight: 400; font-style: normal; } sup, sub { line-height: 1em; } /* Hervorhebung der angeklickten Fußnoten und der Rückverweise in blau */ ol.references > li:target, sup.reference:target { background-color: #def; } /* Hochgestellte Buchstaben in der Einzelnachweiseliste kursiv setzen */ ol.references li a[href|="#cite_ref"] { font-style: italic; } /* Inline-Verwendung der [[:Kategorie:Vorlage:Schwesterprojektverweis|Schwesterprojektverweise]] */ ol.references li div.sisterproject { display: inline !important; } /* Für <nowiki><hiero>…</hiero></nowiki> */ .mw-hierotable, .mw-hierotable th, .mw-hierotable td { border: 0; padding: 0; } /* Für [[MediaWiki:Anoneditwarning]] und weitere Hinweise, die alle untereinander stehen */ #mw-anon-edit-warning, #mw-missingsummary, #wp_talkpagetext { width: 80%; background: #d3e1f2; border: 1px solid #1a47ff; margin: 1em auto; padding: 1em; } /* Bei URLs, die auf unser Projekt und verwandte Projekte verweisen, den Pfeil ausblenden * Dieser Pfeil dient nur dazu, auf externe Ziele hinzuweisen * Auf den Einsatz der Klasse "plainlinks" kann dadurch verzichtet werden */ #content a[href^="http://de.wikipedia.org"], #content a[href^="http://toolserver.org"] { background: none !important; padding-right: 0 !important; } #content .mw-search-formheader div.search-types ul li a[href^="http://de.wikipedia.org"], #content .mw-search-formheader div.search-types ul li a[href^="http://toolserver.org"] { padding-right: 0.5em !important; } /* Falls bei der Seitenbearbeitung vergessen wurde, die Zusammenfassung auszufüllen */ .mw-summarymissed { border: 5px solid red; padding: 2px; } /* Copyrightwarnung */ #editpage-copywarn { border: solid 1px #c00000; font-size: 90%; background-color: #ffffff; } .mw-tos-summary { border: solid 1px #c00000; background-color: #ffffff; padding-left: 1em; } /* +++++ 2. SONSTIGE ANPASSUNGEN (Spezialseiten u. a.) +++++ */ /* Markierung von Redirects in [[Special:Allpages]], [[Special:Watchlist]], Kategorien */ .allpagesredirect, .watchlistredir, .redirect-in-category { font-style: italic; } /* Fettformatierung von Admin-Spezialseiten in [[Special:Specialpages]] abschalten */ .mw-specialpagerestricted strong { font-weight: normal; } /* Legende auf [[Special:Specialpages]] ebenfalls abschalten */ div.mw-specialpages-notes { display: none; } /* Größerer Abstand zwischen TOC-Nummerierung und TOC-Eintrag */ span.tocnumber { margin-right: 0.3em; } /* Skinabhängige absolute Positionierungen ausblenden */ /* Bitte [[MediaWiki Diskussion:Common.css#Absolute_Positionierungen]] beachten */ #coordinates, #coordinates_3_ObenRechts, #issnlink, #editcount, #shortcut, #artikelstadium, .topicon, #spoken-icon, #commons-icon { display: none; } /* Anpassungen für [[:Template:Link_FA]] */ /* hide the template */ #bodyContent span.FA { display: none; } /* change the bullets for links to special articles */ #p-lang li.FA { /* hier immer auch linkFA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/d/d0/Monobook-bullet-star-transparent.png"); } /* change the bullets for links to special articles */ #p-lang li.GA { /* hier immer auch linkGA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/a/a1/Monobook-bullet-star-gray.png"); } /* Verhindere, dass Infoboxen etc. in den Inhalt von Kategorien hineinragen. Das betrifft nur Kategorieseiten. */ #mw-subcategories, #mw-pages { clear: both; } /* DIVs in ImageMaps inlinen (Vorschlag von Revolus) */ .imagemap-inline div { display: inline; } /* [[Special:Hochladen]]: Warnmeldung auf bestehende Dateien, unerwünschte Prefixe usw. deutlicher hervorheben. */ #wpDestFile-warning ul { border: solid red 1px; padding: 1.5em; } /* Warnmeldung für gesperrte Titel */ .mw-titleprotectedwarning { background-color: #eee; border: 2px solid red; padding: 1em; } /* Warnmeldung bei der Bearbeitung von Seiten im MediaWiki-Namensraum */ .mw-editinginterface { background-color: #f9f9f9; border-color: #c00000; border-width: 1px; border-style: solid; padding: 2px; } /* Überschrift 5. und 6. Ordnung proportionaler zu Fließtext */ #content h5 { font-size: 108%; /* Original: 116% */ } #content h6 { font-size: 100%; /* Original: 80% = kleiner als Bodytext, unschön */ } #content h6 .editsection { font-size: 120%; font-weight: normal; } /* Anleitung auf Special:Search */ .mw-searchresult { font-size: 84%; margin: 5px; } /* Gestaltung der Edittools-Leiste */ #specialchars { margin-top: 3px; border: solid 1px #aaaaaa; padding: 1px; text-align: left; background-color: white; } /* Legende für Versionsgeschichte */ .mw-history-legend { font-size: 90%; margin-top: 2px; margin-bottom: 2px; border: solid 1px #e9e9e9; padding: 0 5px 5px 5px; background-color: #f9f9f9; clear: both; } /* +++++ 3. NEUE [[Wikipedia:Hauptseite|HAUPTSEITE]] (ab 2006) +++++ */ /* Kategorie verbergen */ /* Überschrift verbergen */ /* Redirhinweis verbergen - ACHTUNG: Je nach Skin muss jetzt der Abstand zum oberen Rand korrigiert werden */ body.page-Wikipedia_Hauptseite #catlinks, body.page-Wikipedia_Hauptseite h1.firstHeading, body.page-Wikipedia_Hauptseite #contentSub { display: none; } #hauptseite h2 { background-color: #d8e8ff; border: 1px solid #8898bf; font-size: 1em; font-weight: bold; margin-top: 0; margin-bottom: 0; padding-top: 0.1em; padding-bottom: 0.1em; } #hauptseite .inhalt { background-color: #ffffff; border: 1px solid #8898bf; border-top: 0 solid white; padding: 0.3em 0.8em 0.4em 0.8em; } #hauptseite .inhalt hr { background-color: #8898bf; color: #8898bf; height: 1px; margin: 0.5em 0; padding: 0; } #hauptseite .inhalt .mehr { clear: both; font-size: 95%; margin-top: 0.8em; text-align: right; } #hauptseite table { background-color: transparent; } .hauptseite-oben, .hauptseite-links, .hauptseite-rechts { margin-bottom: 1em; } .hauptseite-links { margin-right: 0.5em; } .hauptseite-rechts { margin-left: 0.5em; } .hauptseite-oben h2, .hauptseite-unten h2 { text-align: center; } .hauptseite-oben .inhalt .portale { font-weight: bold; margin-top: 0.2em; margin-bottom: 0.2em; } .hauptseite-oben .inhalt .intern { font-size: 90%; text-align: center; } .hauptseite-links h2, .hauptseite-rechts h2 { text-indent: 0.8em; } #hauptseite-schwesterprojekte .inhalt a { font-weight: bold; } /* IPA links nicht unterstreichen */ .IPA a:link, .IPA a:visited { text-decoration: none; } /* CSS-Klassen für Schriftarten als Workaround für Defizite in alten IE-Versionen. * Achtung: IE6 mag keine Zeilenumbrüche zwischen den Fonts. * In IE8 nicht mehr nötig, soll mit den alten Versionen aussterben. Browserweiche: * http://www.dynamicsitesolutions.com/css/filters/star-html/ * http://www.dynamicsitesolutions.com/css/filters/first-child-plus-html/ */ * html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } *:first-child+html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } * html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } *:first-child+html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } * html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } *:first-child+html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } * html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } *:first-child+html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } * html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } *:first-child+html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } * html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } *:first-child+html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } * html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } *:first-child+html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } * html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } *:first-child+html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } * html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } *:first-child+html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } /* Standardmäßige Ausblendung der Flagged-Revisions-Backlog-Sitenotice */ #mw-oldreviewed-notice { display: none; } /* Standardmäßige Ausblendung der Flagged-Revisions-Kommentarbox */ #mw-commentbox { display: none; } /* Abstand zwischen Liste und Inhaltsverzeichnis erhöhen, siehe http://de.wikipedia.org/w/index.php?title=MediaWiki_Diskussion:Common.css&oldid=51639015#Abstand_vor_Inhaltsverzeichnis */ ul + .toc, ol + .toc { margin-top: 0.5em; } /* höheres Uploadfeld */ #wpUploadDescription { height: 20em; } /* Im Projekt WP:GEO benutzt die [[Vorlage:Coordinate]] das «geo-microformat» zur semantischen Auszeichnung des Texts. Der Inhalt dieses [[Tag (Informatik)|Tags]] ist nicht für den Leser bestimmt. */ .geo { display: none; } /* Patrollink ausblenden, da die Eweiterung hier nicht aktiviert ist und deren Optik zu sehr den gesichteten Versionen ähnelt. */ .fr-diff-patrollink, .patrollink { display: none; } /* Rollback-Knopf auf Beobachtungsliste ausblenden, da es dort nur von sehr beschränktem Nutzen ist und zu sehr vielen Reverts aus Versehen führt */ .page-Spezial_Beobachtungsliste .mw-rollback-link { display: none; } /* </source> */ /* Disable Discussion-tab */ #ca-talk { display: none; } /* reset code style */ code { background-color: none !important; border: none !important; border-radius: 0; padding: 0; } pre { white-space: pre; } e5643165568b8ab916445fb03a43a908cdca35cd FAQ:AVR-Doper 3000 462 1094 2017-04-15T15:30:23Z Chris 2 Test: FAQ im FAQ-Namespace wikitext text/x-wiki ==Was ist der AVR-Doper und was kann er?== Der AVR-Doper ist ein Programmiergerät für AVR-Mikrocontroller (8Bit), die die Programmiermodi SPI und HVSP unterstützen. Er ist Protokollkompatibel zum STK500 und unterstützt einen HID-Modus (Jumper muss vor dem Einstecken gesetzt werden), in dem er keinen Treiber braucht, jedoch nur von entsprechender Software (z. B. AVRdude) bedient werden kann. ==Läuft mein AVR-Doper unter Windows 7?== Ja, aber es erfordert (je nach Verwendung) Tricks. Genaueres ist im [[AVR-Doper#AVR-Doper_unter_Windows_7|Hauptartikel]] beschrieben. Meine Empfehlung unter Windows 7: den HID-Modus in Verbindung mit AVRdude verwenden. Das erspart Frickelei und Ärger. ==Läuft der Doper in AVR Studio 5/Atmel Studio 6?== Bei meinen Versuchen hat es nicht funktioniert, aber das muss nichts heißen. Mit der Zeit bin ich dazu übergegangen, den Doper über AVRdude in Verbindung mit einer Batch-Datei anzusprechen. Über das Tools-Menü in AVR/Atmel Studio lässt sich der Aufruf hierfür relativ einfach integrieren. ==Gibt es zum Doper ein Manual?== Mir wäre nichts bekannt. Allerdings sind die meisten Dokumentationen des STK500 (zumindest softwareseitig) auch für den AVR-Doper gültig, wenn er im STK500-Modus betrieben wird. ==Wie kann ich testen, ob mein AVR-Doper funktioniert?== Das eindeutigste Zeichen für die Funktion ist, dass er am PC erkannt wird und Mikrocontroller beschreiben kann, was dann auch der vollen Funktion entspricht. Die LED Leuchtet nur, wenn auf den Ziel-Chip zugegriffen wird. Weiter kann man die Funktion grundlegend feststellen, indem man kontrolliert, ob an der Kathode von D3 ungefähr 12V anliegen. ==Für was ist welche Buchse gut?== SV1 ist das ISP-Interface (In Circuit Programmig). Also im Prinzip der Hauptgrund, wofür man den Doper gebaut hat. Die Pinbelegung ist abweichend vom "de-facto-Standard", da an Pin 8 und 10 ein UART zur Verfügung gestellt wird. Diese Pins liegen bei anderen Designs auf Masse. SV2 ist für die HVSP (High Voltage Serial Programming). Dies ist besonders interessant, wenn man den Reset-Pin als I/O benutzen möchte. Dazu kann man die Fuse RSTDISBL aktivieren. Das HVSP ist zudem an den Sockeln IC3 und IC4 herausgeführt, sodass man für die kleinen AVRs keinen extra Adapter braucht. Wichtig bei der HVSP ist, dass über die entsprechende Download-Software der Modus auch aktiviert/verwendet wird. ==Was muss ich machen, damit der Doper an meinem Computer funktioniert?== Die entsprechenden Treiber installieren. Nach dem ersten Anschließen sollte der Treiber-Installations-Dialog erscheinen. Bei der Treiberquelle auf Erweitert klicken und die entsprechende INF-Datei (avrdoper.inf bzw. avrdoper-vista.inf) aus dem dekomprimierten Projektarchiv auswählen. Windows 7-User müssen etwas mehr machen: [[AVR-Doper#AVR-Doper_unter_Windows_7|AVR-Doper unter Windows 7]]. ==Muss ich deinen Patch fürs AVR-Studio anwenden?== Nein. ==Wie muss ich welchen Jumper setzen?== (ja, das wurde wirklich gefragt) Im Prinzip steht es im Stromlaufplan. Wenn JP1 geschlossen ist, wird die Zielschaltung über den ISP-Port (SV1) mit 5V versorgt. Mit Schließen des JP2 kann man den Programmiertakt (SCK) reduzieren, falls man eine lange Leitung hat oder auf Nummer sicher gehen will. Ein geschlossener JP3 aktiviert den HID-Modus (siehe weiter oben) - sofern man ihn vor dem Anschließen des Dopers an den PC gesetzt hat. ==Wie verwende ich den Doper?== Es gibt zwar wenig Dokumentation über den AVR-Doper, aber das gibt es. Tipp: readme.txt ist ein ernstzunehmendes Angebot. 635d7199d0eca7c9e4b9f0f4739738aba9626533 MediaWiki:Common.css 8 141 1096 1095 2017-04-15T16:45:46Z Qsysopr 1 Farben für manuelles Highlighting hinzufgefügt css text/css /* <source lang="css"> */ /*-----------------------------------------------------------------------------------------------*/ /* ACHTUNG! Common.css enthält die gemeinsamen Skin-Anpassungen der deutschsprachigen Wikipedia */ /*---------------------------------------------------------------------------------------------*/ /* Common.css ist in drei grundlegende Abschnitte gegliedert: */ /* 1. Editierbare Seiteninhalte */ /* 2. Sonstige Anpassungen (Spezialseiten, u.a.) */ /* 3. Hauptseitenspezifisches */ /* Jede Ergänzung/Änderung muss vorher jeweils für alle Skins auf Tauglichkeit getestet werden, */ /* individuell per User.css! Ist hier erstmal geändert, dauert es dank Cache eine Weile, bis die */ /* Änderungen bei allen Nutzern sichtbar oder, bei Fehlern, korrigiert sind. */ /* +++++ 1. ANPASSUNGEN DER ANZEIGE VON EDITIERBAREN SEITENINHALTEN +++++ */ /* Personennamen in Kapitälchen: class="Person" */ .Person { display: inline; font-variant: small-caps; font-style: normal; } /* [[Wikipedia:Zitate|Zitate]] (siehe [[Vorlage:Zitat]]) */ p.Zitat { font-style: normal; margin-bottom: 0; } p.cite { margin-top: 0; padding-left: 1em; } /* [[Wikipedia:Quellenangaben|Quellenangaben]] nicht kursiv, da sie ggf. verschiedene Bestandteile enthalten */ cite { font-style: normal; } /* Stylesheet-Ergänzung zu Standard-[[Wikipedia:Navigationsleisten|Navigationsleisten]] */ div.BoxenVerschmelzen, div.NavFrame { margin: 1.5em 0 0; padding: 2px; border: 1px solid #aaaaaa; text-align: center; border-collapse: collapse; font-size: 95%; clear: both; } div.BoxenVerschmelzen div.NavFrame, div.NavFrame + div.NavFrame { margin-top: 0; } div.BoxenVerschmelzen div.NavFrame { border-style: none; border-style: hidden; } div.NavFrame + div.NavFrame { border-top-style: none; border-top-style: hidden; } div.NavPic { margin: 0; padding: 2px; float: left; } div.NavFrame div.NavHead { font-weight: bold; font-size: 100%; background-color: #efefef; } div.NavFrame p, div.NavFrame div.NavContent, div.NavFrame div.NavContent p { font-size: 100%; } div.NavEnd { margin: 0; padding: 0; line-height: 1px; clear: both; } /* Stylesheet fuer den 'Ausklappen'-Button an Navileisten, der in [[MediaWiki:Common.js]] implementiert wird */ .NavToggle { font-size: x-small; float: right; } /* Workaround für Internet Explorer 6 */ div.NavFrame, div.NavPic, .NavToggle { position: relative; } /* Stylesheet-Ergänzung zu SideBoxen (ehedem [[Wikipedia:TownBox|TownBox]]) */ div.sideBox { position: relative; float: right; background: white; margin-left: 1em; border: 1px solid gray; padding: 0.3em; width: 200px; overflow: hidden; clear: right; } div.sideBox dl { padding: 0; margin: 0 0 0.3em 0; font-size: 96%; } div.sideBox dl dt { background: none; margin: 0.4em 0 0 0; } div.sideBox dl dd { margin: 0.1em 0 0 1.1em; background-color: #f3f3f3; } /* Stylesheet-Ergänzung zu [[Wikipedia:Taxoboxen|Taxoboxen]] und [[Wikipedia:Paläoboxen|Paläoboxen]] */ table.taxobox, table.palaeobox { border-collapse: collapse; border: 1px solid gray; float: right; clear: right; margin-left: 0.5em; background-color: white; } table.taxobox th { background-color: #9bcd9b; } table.palaeobox th { background-color: #e7dcc3; } table.taxobox th, table.palaeobox th { border: solid 1px gray; text-align: center; font-weight: bold; } table.taxobox td, table.palaeobox td { vertical-align: top; } table.taxobox .Person, table.palaeobox .Person { font-style: normal; } table.taxobox div.thumb, table.taxobox div.thumb * { background-color: #f9f9f9; } table.taxobox div.thumb, table.taxobox div.thumb *, table.palaeobox div.thumb, table.palaeobox div.thumb * { margin: 0 auto; padding: 0; float: none; border: none; } table.taxobox div.magnify, table.palaeobox div.magnify { display: none; } table.taxobox tr td div.thumb div div.thumbcaption { text-align: center; } table.palaeobox tr td div.thumb div div.thumbcaption { text-align: left; } table.taxobox td.Person, table.palaeobox td.Person { text-align: center; display: block; } table.taxobox td.taxo-name, table.taxobox td.taxo-bild, table.palaeobox td.taxo-name, table.palaeobox td.taxo-bild, table.palaeobox td.taxo-zeit { text-align: center; } table.palaeobox td.taxo-ort { text-align: left; } /* aus Vorlage zur Entlastung, skinabhängigen Darstellung und Kombinierbarkeit hierher ausgelagert */ .wikitable, .prettytable { margin: 1em 1em 1em 0; background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse; } .prettytable th, .prettytable td { border: 1px #aaa solid; padding: 0.2em; } .prettytable th { text-align: center; } .prettytable caption { font-weight: bold; } /* Zebra-Tabellen */ table.wikitable.zebra tr:nth-child(even) { background: white; } .nogrid th, .nogrid td { border: none; } div.float-left, table.float-left, .float-left { float: left; clear: left; } div.float-right, table.float-right, .float-right { float: right; clear: right; margin: 1em 0 1em 1em; } div.centered, table.centered, .centered { margin-left: auto; margin-right: auto; } .toptextcells td { vertical-align: top; } /* Bitte KEINE weiteren Definitionen dieser Art für Boxen hier, das gehört in entsprechende Vorlagen! */ /* Hier 20 Mal Trivialitäten wie "text-align:center" zu definieren verlangsamt alles und ist nicht */ /* Sinn der Sache. (Und wer nicht weiß warum, hat's nicht verstanden.) */ /* Do not expand [[Wikipedia:WikiProjekt Georeferenzierung|kvaleberg.com-URLs]] for printing */ #content span.coordinates a.external.text:after, #content span.coordinates a.external.autonumber:after, #content div.coordinates a.external.text:after, #content div.coordinates a.external.autonumber:after { content: ""; } /* Do not expand URLs for printing */ #content span.plainlinks-print a.external.text:after, #content span.plainlinks-print a.external.autonumber:after, #content div.plainlinks-print a.external.text:after, #content div.plainlinks-print a.external.autonumber:after { content: ""; } /* Metadaten (bspw. [[Wikipedia:Personendaten|Personendaten]]) */ table.metadata { border: 1px solid #aaaaaa; display: none; } .metadata-label { color: #aaaaaa; } span.metadata, span.metadata-inline { display: none; } /* * Farbdefinitionen für Rahmen und Hintergründe von [[Wikipedia:Textbausteine|Textbausteinen]]. * Hier: Standardvorgaben für "dunkle Schrift auf hellem Grund". * Für Hell-auf-dunkel-Skins ([[MediaWiki:Amethyst.css|Amethyst]]) müssen dort entsprechende Definitionen * zusätzlich eingetragen werden! Anpassungen für andere Skins sind optional. * (Die Angaben der Rahmenstärke dienen der Bequemlichkeit, so dass man * für dünne Rahmen nur noch "border-style" angeben muss.) */ .rahmenfarbe1 { /* Wie Inhaltsverzeichnis */ border-color: #aaaaaa; border-width: 1px; } .rahmenfarbe2 { /* Unauffällig, geringer Kontrast */ border-color: #e9e9e9; border-width: 1px; } .rahmenfarbe3 { /* "Rot", auffällig */ border-color: #c00000; border-width: 1px; } .rahmenfarbe4 { /* Neutrale Farbe, deutlich */ border-color: #8888aa; border-width: 1px; } .rahmenfarbe5 { /* "Schwarz", hoher Kontrast */ border-color: #000000; border-width: 1px; } tr.hintergrundfarbe1 th, tr th.hintergrundfarbe1, table.hintergrundfarbe1, .hintergrundfarbe1 { /* Wie Inhaltsverzeichnis */ background-color: #f9f9f9; } tr.hintergrundfarbe2 th, tr th.hintergrundfarbe2, table.hintergrundfarbe2, .hintergrundfarbe2 { /* "Weiß", für Nicht-Artikel-Seiten, neutral */ background-color: #ffffff; } tr.hintergrundfarbe3 th, tr th.hintergrundfarbe3, table.hintergrundfarbe3, .hintergrundfarbe3 { /* "Gelb", auffällig */ background-color: #ffff40; } tr.hintergrundfarbe4 th, tr th.hintergrundfarbe4, table.hintergrundfarbe4, .hintergrundfarbe4 { /* Sehr auffällig */ background-color: #ffaa00; } tr.hintergrundfarbe5 th, tr th.hintergrundfarbe5, table.hintergrundfarbe5, .hintergrundfarbe5 { /* Neutral, abgesetzt */ background-color: #e0e0e0; } tr.hintergrundfarbe6 th, tr th.hintergrundfarbe6, table.hintergrundfarbe6, .hintergrundfarbe6 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b3b7ff; } tr.hintergrundfarbe7 th, tr th.hintergrundfarbe7, table.hintergrundfarbe7, .hintergrundfarbe7 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffcbcb; } tr.hintergrundfarbe8 th, tr th.hintergrundfarbe8, table.hintergrundfarbe8, .hintergrundfarbe8 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffebad; } tr.hintergrundfarbe9 th, tr th.hintergrundfarbe9, table.hintergrundfarbe9, .hintergrundfarbe9 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b9ffc5; } /* Keine Vergrößerung der Zeilenhöhe durch hochgestellte Zahlen der Fußnoten */ sup.reference { font-weight: 400; font-style: normal; } sup, sub { line-height: 1em; } /* Hervorhebung der angeklickten Fußnoten und der Rückverweise in blau */ ol.references > li:target, sup.reference:target { background-color: #def; } /* Hochgestellte Buchstaben in der Einzelnachweiseliste kursiv setzen */ ol.references li a[href|="#cite_ref"] { font-style: italic; } /* Inline-Verwendung der [[:Kategorie:Vorlage:Schwesterprojektverweis|Schwesterprojektverweise]] */ ol.references li div.sisterproject { display: inline !important; } /* Für <nowiki><hiero>…</hiero></nowiki> */ .mw-hierotable, .mw-hierotable th, .mw-hierotable td { border: 0; padding: 0; } /* Für [[MediaWiki:Anoneditwarning]] und weitere Hinweise, die alle untereinander stehen */ #mw-anon-edit-warning, #mw-missingsummary, #wp_talkpagetext { width: 80%; background: #d3e1f2; border: 1px solid #1a47ff; margin: 1em auto; padding: 1em; } /* Bei URLs, die auf unser Projekt und verwandte Projekte verweisen, den Pfeil ausblenden * Dieser Pfeil dient nur dazu, auf externe Ziele hinzuweisen * Auf den Einsatz der Klasse "plainlinks" kann dadurch verzichtet werden */ #content a[href^="http://de.wikipedia.org"], #content a[href^="http://toolserver.org"] { background: none !important; padding-right: 0 !important; } #content .mw-search-formheader div.search-types ul li a[href^="http://de.wikipedia.org"], #content .mw-search-formheader div.search-types ul li a[href^="http://toolserver.org"] { padding-right: 0.5em !important; } /* Falls bei der Seitenbearbeitung vergessen wurde, die Zusammenfassung auszufüllen */ .mw-summarymissed { border: 5px solid red; padding: 2px; } /* Copyrightwarnung */ #editpage-copywarn { border: solid 1px #c00000; font-size: 90%; background-color: #ffffff; } .mw-tos-summary { border: solid 1px #c00000; background-color: #ffffff; padding-left: 1em; } /* +++++ 2. SONSTIGE ANPASSUNGEN (Spezialseiten u. a.) +++++ */ /* Markierung von Redirects in [[Special:Allpages]], [[Special:Watchlist]], Kategorien */ .allpagesredirect, .watchlistredir, .redirect-in-category { font-style: italic; } /* Fettformatierung von Admin-Spezialseiten in [[Special:Specialpages]] abschalten */ .mw-specialpagerestricted strong { font-weight: normal; } /* Legende auf [[Special:Specialpages]] ebenfalls abschalten */ div.mw-specialpages-notes { display: none; } /* Größerer Abstand zwischen TOC-Nummerierung und TOC-Eintrag */ span.tocnumber { margin-right: 0.3em; } /* Skinabhängige absolute Positionierungen ausblenden */ /* Bitte [[MediaWiki Diskussion:Common.css#Absolute_Positionierungen]] beachten */ #coordinates, #coordinates_3_ObenRechts, #issnlink, #editcount, #shortcut, #artikelstadium, .topicon, #spoken-icon, #commons-icon { display: none; } /* Anpassungen für [[:Template:Link_FA]] */ /* hide the template */ #bodyContent span.FA { display: none; } /* change the bullets for links to special articles */ #p-lang li.FA { /* hier immer auch linkFA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/d/d0/Monobook-bullet-star-transparent.png"); } /* change the bullets for links to special articles */ #p-lang li.GA { /* hier immer auch linkGA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/a/a1/Monobook-bullet-star-gray.png"); } /* Verhindere, dass Infoboxen etc. in den Inhalt von Kategorien hineinragen. Das betrifft nur Kategorieseiten. */ #mw-subcategories, #mw-pages { clear: both; } /* DIVs in ImageMaps inlinen (Vorschlag von Revolus) */ .imagemap-inline div { display: inline; } /* [[Special:Hochladen]]: Warnmeldung auf bestehende Dateien, unerwünschte Prefixe usw. deutlicher hervorheben. */ #wpDestFile-warning ul { border: solid red 1px; padding: 1.5em; } /* Warnmeldung für gesperrte Titel */ .mw-titleprotectedwarning { background-color: #eee; border: 2px solid red; padding: 1em; } /* Warnmeldung bei der Bearbeitung von Seiten im MediaWiki-Namensraum */ .mw-editinginterface { background-color: #f9f9f9; border-color: #c00000; border-width: 1px; border-style: solid; padding: 2px; } /* Überschrift 5. und 6. Ordnung proportionaler zu Fließtext */ #content h5 { font-size: 108%; /* Original: 116% */ } #content h6 { font-size: 100%; /* Original: 80% = kleiner als Bodytext, unschön */ } #content h6 .editsection { font-size: 120%; font-weight: normal; } /* Anleitung auf Special:Search */ .mw-searchresult { font-size: 84%; margin: 5px; } /* Gestaltung der Edittools-Leiste */ #specialchars { margin-top: 3px; border: solid 1px #aaaaaa; padding: 1px; text-align: left; background-color: white; } /* Legende für Versionsgeschichte */ .mw-history-legend { font-size: 90%; margin-top: 2px; margin-bottom: 2px; border: solid 1px #e9e9e9; padding: 0 5px 5px 5px; background-color: #f9f9f9; clear: both; } /* +++++ 3. NEUE [[Wikipedia:Hauptseite|HAUPTSEITE]] (ab 2006) +++++ */ /* Kategorie verbergen */ /* Überschrift verbergen */ /* Redirhinweis verbergen - ACHTUNG: Je nach Skin muss jetzt der Abstand zum oberen Rand korrigiert werden */ body.page-Wikipedia_Hauptseite #catlinks, body.page-Wikipedia_Hauptseite h1.firstHeading, body.page-Wikipedia_Hauptseite #contentSub { display: none; } #hauptseite h2 { background-color: #d8e8ff; border: 1px solid #8898bf; font-size: 1em; font-weight: bold; margin-top: 0; margin-bottom: 0; padding-top: 0.1em; padding-bottom: 0.1em; } #hauptseite .inhalt { background-color: #ffffff; border: 1px solid #8898bf; border-top: 0 solid white; padding: 0.3em 0.8em 0.4em 0.8em; } #hauptseite .inhalt hr { background-color: #8898bf; color: #8898bf; height: 1px; margin: 0.5em 0; padding: 0; } #hauptseite .inhalt .mehr { clear: both; font-size: 95%; margin-top: 0.8em; text-align: right; } #hauptseite table { background-color: transparent; } .hauptseite-oben, .hauptseite-links, .hauptseite-rechts { margin-bottom: 1em; } .hauptseite-links { margin-right: 0.5em; } .hauptseite-rechts { margin-left: 0.5em; } .hauptseite-oben h2, .hauptseite-unten h2 { text-align: center; } .hauptseite-oben .inhalt .portale { font-weight: bold; margin-top: 0.2em; margin-bottom: 0.2em; } .hauptseite-oben .inhalt .intern { font-size: 90%; text-align: center; } .hauptseite-links h2, .hauptseite-rechts h2 { text-indent: 0.8em; } #hauptseite-schwesterprojekte .inhalt a { font-weight: bold; } /* IPA links nicht unterstreichen */ .IPA a:link, .IPA a:visited { text-decoration: none; } /* CSS-Klassen für Schriftarten als Workaround für Defizite in alten IE-Versionen. * Achtung: IE6 mag keine Zeilenumbrüche zwischen den Fonts. * In IE8 nicht mehr nötig, soll mit den alten Versionen aussterben. Browserweiche: * http://www.dynamicsitesolutions.com/css/filters/star-html/ * http://www.dynamicsitesolutions.com/css/filters/first-child-plus-html/ */ * html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } *:first-child+html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } * html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } *:first-child+html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } * html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } *:first-child+html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } * html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } *:first-child+html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } * html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } *:first-child+html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } * html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } *:first-child+html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } * html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } *:first-child+html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } * html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } *:first-child+html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } * html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } *:first-child+html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } /* Standardmäßige Ausblendung der Flagged-Revisions-Backlog-Sitenotice */ #mw-oldreviewed-notice { display: none; } /* Standardmäßige Ausblendung der Flagged-Revisions-Kommentarbox */ #mw-commentbox { display: none; } /* Abstand zwischen Liste und Inhaltsverzeichnis erhöhen, siehe http://de.wikipedia.org/w/index.php?title=MediaWiki_Diskussion:Common.css&oldid=51639015#Abstand_vor_Inhaltsverzeichnis */ ul + .toc, ol + .toc { margin-top: 0.5em; } /* höheres Uploadfeld */ #wpUploadDescription { height: 20em; } /* Im Projekt WP:GEO benutzt die [[Vorlage:Coordinate]] das «geo-microformat» zur semantischen Auszeichnung des Texts. Der Inhalt dieses [[Tag (Informatik)|Tags]] ist nicht für den Leser bestimmt. */ .geo { display: none; } /* Patrollink ausblenden, da die Eweiterung hier nicht aktiviert ist und deren Optik zu sehr den gesichteten Versionen ähnelt. */ .fr-diff-patrollink, .patrollink { display: none; } /* Rollback-Knopf auf Beobachtungsliste ausblenden, da es dort nur von sehr beschränktem Nutzen ist und zu sehr vielen Reverts aus Versehen führt */ .page-Spezial_Beobachtungsliste .mw-rollback-link { display: none; } /* </source> */ /* Disable Discussion-tab */ #ca-talk { display: none; } /* reset code style */ code { background-color: none !important; border: none !important; border-radius: 0; padding: 0; } pre { white-space: pre; } /* highlighting */ .hb1 { background-color: #C1F5C1; } .hb2 { background-color: #CDC2EF; } .hb3 { background-color: #FFF6C9; } .hb4 { background-color: #FFC9C9; } .hb5 { background-color: #BED8ED; } .hb6 { background-color: #EDBBED; } .hb7 { background-color: #F4FDC7; } .hb8 { background-color: #FFE8C9; } .hf1 { color: #66D766; } .hf2 { color: #7C67C0; } .hf3 { color: #FFE879; } .hf4 { color: #FF7979; } .hf5 { color: #5D90B7; } .hf6 { color: #B857B8; } .hf7 { color: #E2F876; } .hf8 { color: #FFC679; } b84427940d437fb10b8110bd4c73c44a005107f1 Prozeda-Decoder 0 460 1097 1093 2017-04-15T16:46:16Z Qsysopr 1 Farben für manuelles Highlighting sind nun in den Common styles wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FTDI2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <source lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </source> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <source lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </source> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <source lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </source> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <source lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </source> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task<code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick<code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in prozeda_tick wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] 5af3e401e702162908a0d41d51e7a03bcae53849 1098 1097 2017-04-17T13:24:50Z Chris 2 /* Angezapft */ Code-Tags korrigiert wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FTDI2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <source lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </source> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <source lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </source> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <source lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </source> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <source lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </source> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] 9affef9f2f9fb78dc1288d862e034fc62c5257f3 1132 1098 2018-04-15T19:53:57Z Chris 2 /* Anmerkungen */ Verweis auf Pirozeda hinzugefügt wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FTDI2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <source lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </source> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <source lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </source> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <source lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </source> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <source lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </source> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] 113e484e73514fa69f74d26eb62c788a224f2300 1133 1132 2018-04-15T19:54:42Z Chris 2 Kategorie hinzugefügt wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FTDI2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <source lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </source> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <source lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </source> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <source lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </source> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <source lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </source> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] c3b43a40f22e6d1c23776223e2de15e3e1691107 1145 1133 2018-04-16T20:13:16Z Chris 2 Einblick ins Innenleben des Reglers hinzugefügt wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FTDI2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Einblick in den Regler= Ein Griff in die Zukunft - 11/2017: Im Rahmen der [[Pirozeda]]-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen: <gallery> sungo_sxlplus.JPG | SUNGO SXLplus von außen sungo_sxlplus_ctrl_bot.jpg | Controllerboard vorne sungo_sxlplus_ctrl_top.jpg | Controllerboard hinten sungo_sxlplus_pwr_top.jpg | Leistungsboard vorne sungo_sxlplus_pwr_bot.jpg | Leistungsboard hinten sungo_sxlplus_pwr_port.jpg | Anschluss des Datasticks sungo_sxlplus_pwr_switch.jpg | Schaltmodule </gallery> ==Controllerboard== Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte. Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war. Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt. Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt... ==Leistungsboard== So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen. Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter. Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder. Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können. =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <source lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </source> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <source lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </source> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <source lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </source> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <source lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </source> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] 6a0b8f3e46e24332ed6b63658094cc8188839ac4 Hauptseite 0 1 1099 1089 2017-04-17T14:19:02Z Chris 2 Neues: Mediawiki-Update & Prozeda-Decoder wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556&preview=true Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *23.06.2016 [[Minichirp]] *02.01.2016 [[Lichtsensor Avago APDS-9300]] *01.04.2015 [[Mini-Schaltwandler]] ==Änderungen== *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. 922acbeac06a7426a8d375616c57afa14dc9ad73 1100 1099 2017-04-17T14:19:43Z Chris 2 Naja, vielleicht nicht unbedingt die Preview-Adresse ;) wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *23.06.2016 [[Minichirp]] *02.01.2016 [[Lichtsensor Avago APDS-9300]] *01.04.2015 [[Mini-Schaltwandler]] ==Änderungen== *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. 98bb2595c1175327833fa60bfad36c69ea38eba5 1113 1100 2017-11-12T18:37:44Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *23.06.2016 [[Minichirp]] *02.01.2016 [[Lichtsensor Avago APDS-9300]] ==Änderungen== *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. 82ee7770b5032c8191a4a3859ead70df299cc435 1134 1113 2018-04-15T19:56:38Z Chris 2 /* Neues */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *15.04.2017 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *23.06.2016 [[Minichirp]] ==Änderungen== *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. 69dda5fe8e8d0a366274093d35c08487e112a503 Minichirp 0 438 1101 1044 2017-05-06T20:54:25Z Chris 2 Warenkorb bei Reichelt hinzugefügt wikitext text/x-wiki [[Datei:Chirp_pot.jpg|thumb|Minichirp in Lauerstellung]] Ich weiß gar nicht mehr, wie ich darauf gestoßen bin und eigentlich fühlen sich die Pflanzen in der näheren Umgebung nicht ganz unwohl (bis auf den Weihnachtsstern, der mir nach einer Woche verreckt ist). Trotzdem wollte ich einen [http://wemakethings.net/chirp/ Chirp] haben. Dabei handelt es sich eine von Mic von wemakethings.net designtes Stück Hardware, das man in die Erde der zu überwachenden Pflanze steckt, anlernt und dann angezirpt wird, wenn man vergisst zu gießen. So richtig gut hat mir das Layout aber nicht gefallen - das geht sicher kleiner und vielleicht schicker! = Komponenten = Das Original verwendet bedrahtete Bauteile (Taster und Schallgeber), die zudem relativ groß sind. Reichelt als angepeilten Quelle für die Bauteile bietet alles Benötigte im SMD-Gehäuse an. Im Fall des Piepsers zwar etwas teurer aber man kann eben nicht alles haben. Beim Batteriehalter habe ich länger gehadert - der Blechstreifen-Typ ist zwar günstig und sehr kompakt aber die zweite Kontaktfläche der Batterie wäre die Leiterkarte. Das raubt zum einen Platz für Leiterbahnen und zum anderen oxidiert die verzinnte Oberfläche irgendwann. Das macht die Schaltung unzuverlässig. Vergolden kann man zwar, aber das muss man bezahlen. Okay, den besseren Batteriehalter zwar auch, aber unterm Strich kommt es wahrscheinlich billiger. Der Konnektor für das ISP- bzw. auch I²C-Interface (wenn man ihn dazuzählen will) soll auch kleiner werden. Eine Reihe an 6 Kontakten mit 1,27 mm Rastermaß muss reichen - das ist nicht nur kompakter, sondern man kann auch die üblichen Flachbandkabel direkt anlöten. Die Anschlussbelegung folgt der des 6-pinnigen ISP-Steckers. Schlussendlich bin ich bei folgender Materialliste gelandet: {| class="wikitable" ! Menge !! Name !! Wert !! Bestellname Reichelt |- | 1 || LED1 || || LED EL 0603 GR1 |- | 1 || R2 || 100 || SMD-0603 100 |- | 2 || C1, C2 || 100n || X7R-G0603 100N |- | 4 || R1, R3, R4, R6 || 10k || SMD-0603 10k |- | 2 || C3, C4 || 1u || X7R-G0805 1,0/16 |- | 1 || R5 || 470k || SMD-0603 470K |- | 1 || IC1 || ATTINY44A || ATTINY 44A-SSU |- | 1 || D1 || BAT54 || BAT 54 SMD |- | 1 || Q1 || BSS138 || BSS 138 SMD |- | 1 || S1 || KMR2 || KMR 231 G LFS |- | 1 || X2 || KZH20SMD-2 || KZH 20SMD-2 |- | 1 || SG2 || SMD-08A03 || SMD-08A03 |} [https://www.reichelt.de/my/1346699|Warenkorb bei Reichelt] = Layout = Eine feste Größe der Leiterkarte habe ich nicht vorgegeben, nur ein paar Einschränkungen und Ziele: Fläche so gut ausnutzen wie möglich (und dadurch so klein wie möglich werden) und die längere Kante sollte höchstens 10 cm sein - damit es zum einen in EAGLE Light geroutet werden kann und die Produktion in Fernost günstig bleibt. Die Platzierung ist geradeaus: der Batteriehalter ist am größten und nimmt die Unterseite in Beschlag, oben kommt der ganze Rest. Alles was den Benutzer betrifft, kommt ans Ende: Buzzer, LED, Taster und Schnittstelle, damit das Zeug möglichst weit von der feuchten Erde weg ist. Der Mikrocontroller samt einer Reihe Bauteile ist ca. 10 mm breit, das Ziel für die Breite der Leiterkarte somit auf "ein bisschen mehr" gesteckt. Dem geschuldet wandert die LED auf die Unterseite und der Batteriehalter samt Batterie schaut recht großzügig heraus. Nicht ganz optimal aber die Leiterkarte bleibt klein. Die Sensorfläche ist deutlich größer als beim Original - ob und welchen Einfluss das auf die Messung hat, muss ich noch herausfinden. Da die Software adaptiv arbeitet, sollte sie damit aber klar kommen. Im Bereich der in die Erde kommt, sind bewusst keine Vias. Auch wenn dadurch die zwei Masseflächen elektrisch gesehen etwas voneinander abdriften: oft schaut bei den Bohrungen das Kupfer heraus. Zwar soll Kupfer Schnittblumen helfen, länger frisch zu bleiben, die Auswirkungen auf andere Pflanzen muss ich damit aber nicht unbedingt herausfinden. Zudem dürften die Durchkontaktierungen mit der Zeit Korrosionen zum Opfer fallen - dann kann man sie sich auch gleich sparen. Offen bleibt jedoch die Frage, wie sich der Lötstopplack mit Erde und Feuchtigkeit verträgt (oder andersrum: wie die Pflanze die Chemie abkann). Auch auf der Seite von wemakethings steht dazu leider nichts. Ein weiteres Detail ist die runde Spitze auf Sensorseite - diese soll das Einstecken in den Topf erleichtern. Analogie (schlechter Wortwitz inbegriffen): Nein, kein Fieberthermometer, sondern diese Einsteckkärtchen, die man oft in Pflanzkübeln findet. Nach ein paar Stunden Grübeln steht das Layout. Zufrieden ist man natürlich nie, aber es hätte auch schlechter sein können: <gallery> Datei:Chirp_sch.png|Schaltplan des Minichirp Datei:Chirp_brd.png|Layout des Minchirp </gallery> = Aufbau = Der Aufbau ist weitestgehend harmlos. Lediglich an einer Stelle ist es ziemlich eng: das nicht genutzte Eck vom Signalgeber kommt den Pads vom Taster gefährlich nahe und obwohl ich mich beim Footprint des kleinen Lautsprechers an das Datenblatt gehalten habe, scheinen die Pins nicht ganz auf die Pads zu passen. Beim Bestücken sollte man jedoch darauf achten, den Taster vor dem Piepser aufzulöten und den Batteriehalter als allerletztes einzulöten. Zum einen, weil sonst die Lötspitze zu stinken anfängt, zum anderen, weil Piepser und Batteriehalter die klobigsten Komponenten sind und sie dadurch das Löten der anderen Bauteile deutlich erschweren. {{Infobox AVR | Typ = ATtiny44 | Takt = 1 | FuseH = DE | FuseL = E2 }} Zum Flashen muss ein Flachbandkabel an den Konnektor, mit nicht eingelegter Batterie können Fuses und Flash geschrieben werden, zumindest wenn man die passende Hexfile hat. Auf Github liegt sie zumindest nicht, also den Compiler selbst anwerfen. <gallery> Datei:Chirp_asm_top.jpg|Von oben... Datei:Chirp_asm_bot.jpg|...und unten </gallery> = Bedienung = Kurz nachdem die Firmware auf dem Controller gelandet ist, fängt das Teil auch an zu Zirpen. Was ich nicht wusste: wenn nichts im EEPROM steht, wird über die LED auch gleich die Referenzhelligkeit gemessen und abgelegt. Später wird erst ab diesem Wert gezirpt. Grundlegend keine schlechte Idee, nur war zu diesem Zeitpunkt die Schreibtischleuchte perfekt auf die LED ausgerichtet. Im etwas dunkleren Wohnzimmer wurde dann geblinkt statt gezirpt. Also die gerade abgeknipste Leitung wieder anlöten, und den EEPROM löschen. So viel vom ersten Fallstrick bei der Bedienung. Ansonsten ist das Teil einfach zu bedienen: Nach dem ersten Einschalten oder dem Drücken des (Re-)Set-Tasters wird die "Trocken-Feuchtigkeit" gemessen, also jene wenn man die Pflanze gießen sollte. Die Messung wird nach ca. 5 Sekunden mit einem längeren Zirpen quittiert. Anschließend kann man die Pflanze (aber nicht den Chirp) mit Wasser versorgen. Die Elektronik wacht immer wieder auf und misst die Kapazität der Sensorfläche. Wird eine zu niedrige Feuchtigkeit ermittelt, legt bei Helligkeit die zirpende Grille los (nein, nicht [https://www.youtube.com/results?search_query=zirpende+Grille+MIB die]). Bei Dunkelheit wird man durch die LED benachrichtigt. Erkennt der Mikrocontroller, dass die Feuchtigkeit gestiegen ist, wird das Gießen wiederum mit einem länglichen Zirpen bestätigt. Nachdem die erste Woche bei meinen widerstandsfähigeren Topfpflanzen (die für den ersten Test herhalten mussten) vorbei war, wurde ich etwas ungeduldig. Kein Zirpen. Einen Tag später legte sie aber los. Nicht zu laut aber dennoch gut hörbar. Bis jetzt sehr zuverlässig. = Lizenz = Das Originalprojekt ist unter der CERN OHL 1.1 lizenziert. Der Einfachheit halber ziehe ich gleich. = Download = * [[Datei:Chirp.zip|Chirp.zip]] = Wer will? = Es gibt noch ein paar der Leiterkarten. Wer eine will, kann sie gerne kostenlos aber gegen Versandkosten haben. Und nein: ich verkaufe keine fertig bestückten Chirps. Vielleicht übernimmt ja Mic mein Layout und bietet es auf Tindie an!? [[Kategorie:AVR]] 01fa3724880204e05a158d633464fae6c1e661e3 1102 1101 2017-05-06T20:55:02Z Chris 2 ...und natürlich falsch eingegeben... wikitext text/x-wiki [[Datei:Chirp_pot.jpg|thumb|Minichirp in Lauerstellung]] Ich weiß gar nicht mehr, wie ich darauf gestoßen bin und eigentlich fühlen sich die Pflanzen in der näheren Umgebung nicht ganz unwohl (bis auf den Weihnachtsstern, der mir nach einer Woche verreckt ist). Trotzdem wollte ich einen [http://wemakethings.net/chirp/ Chirp] haben. Dabei handelt es sich eine von Mic von wemakethings.net designtes Stück Hardware, das man in die Erde der zu überwachenden Pflanze steckt, anlernt und dann angezirpt wird, wenn man vergisst zu gießen. So richtig gut hat mir das Layout aber nicht gefallen - das geht sicher kleiner und vielleicht schicker! = Komponenten = Das Original verwendet bedrahtete Bauteile (Taster und Schallgeber), die zudem relativ groß sind. Reichelt als angepeilten Quelle für die Bauteile bietet alles Benötigte im SMD-Gehäuse an. Im Fall des Piepsers zwar etwas teurer aber man kann eben nicht alles haben. Beim Batteriehalter habe ich länger gehadert - der Blechstreifen-Typ ist zwar günstig und sehr kompakt aber die zweite Kontaktfläche der Batterie wäre die Leiterkarte. Das raubt zum einen Platz für Leiterbahnen und zum anderen oxidiert die verzinnte Oberfläche irgendwann. Das macht die Schaltung unzuverlässig. Vergolden kann man zwar, aber das muss man bezahlen. Okay, den besseren Batteriehalter zwar auch, aber unterm Strich kommt es wahrscheinlich billiger. Der Konnektor für das ISP- bzw. auch I²C-Interface (wenn man ihn dazuzählen will) soll auch kleiner werden. Eine Reihe an 6 Kontakten mit 1,27 mm Rastermaß muss reichen - das ist nicht nur kompakter, sondern man kann auch die üblichen Flachbandkabel direkt anlöten. Die Anschlussbelegung folgt der des 6-pinnigen ISP-Steckers. Schlussendlich bin ich bei folgender Materialliste gelandet: {| class="wikitable" ! Menge !! Name !! Wert !! Bestellname Reichelt |- | 1 || LED1 || || LED EL 0603 GR1 |- | 1 || R2 || 100 || SMD-0603 100 |- | 2 || C1, C2 || 100n || X7R-G0603 100N |- | 4 || R1, R3, R4, R6 || 10k || SMD-0603 10k |- | 2 || C3, C4 || 1u || X7R-G0805 1,0/16 |- | 1 || R5 || 470k || SMD-0603 470K |- | 1 || IC1 || ATTINY44A || ATTINY 44A-SSU |- | 1 || D1 || BAT54 || BAT 54 SMD |- | 1 || Q1 || BSS138 || BSS 138 SMD |- | 1 || S1 || KMR2 || KMR 231 G LFS |- | 1 || X2 || KZH20SMD-2 || KZH 20SMD-2 |- | 1 || SG2 || SMD-08A03 || SMD-08A03 |} [https://www.reichelt.de/my/1346699 Warenkorb bei Reichelt] = Layout = Eine feste Größe der Leiterkarte habe ich nicht vorgegeben, nur ein paar Einschränkungen und Ziele: Fläche so gut ausnutzen wie möglich (und dadurch so klein wie möglich werden) und die längere Kante sollte höchstens 10 cm sein - damit es zum einen in EAGLE Light geroutet werden kann und die Produktion in Fernost günstig bleibt. Die Platzierung ist geradeaus: der Batteriehalter ist am größten und nimmt die Unterseite in Beschlag, oben kommt der ganze Rest. Alles was den Benutzer betrifft, kommt ans Ende: Buzzer, LED, Taster und Schnittstelle, damit das Zeug möglichst weit von der feuchten Erde weg ist. Der Mikrocontroller samt einer Reihe Bauteile ist ca. 10 mm breit, das Ziel für die Breite der Leiterkarte somit auf "ein bisschen mehr" gesteckt. Dem geschuldet wandert die LED auf die Unterseite und der Batteriehalter samt Batterie schaut recht großzügig heraus. Nicht ganz optimal aber die Leiterkarte bleibt klein. Die Sensorfläche ist deutlich größer als beim Original - ob und welchen Einfluss das auf die Messung hat, muss ich noch herausfinden. Da die Software adaptiv arbeitet, sollte sie damit aber klar kommen. Im Bereich der in die Erde kommt, sind bewusst keine Vias. Auch wenn dadurch die zwei Masseflächen elektrisch gesehen etwas voneinander abdriften: oft schaut bei den Bohrungen das Kupfer heraus. Zwar soll Kupfer Schnittblumen helfen, länger frisch zu bleiben, die Auswirkungen auf andere Pflanzen muss ich damit aber nicht unbedingt herausfinden. Zudem dürften die Durchkontaktierungen mit der Zeit Korrosionen zum Opfer fallen - dann kann man sie sich auch gleich sparen. Offen bleibt jedoch die Frage, wie sich der Lötstopplack mit Erde und Feuchtigkeit verträgt (oder andersrum: wie die Pflanze die Chemie abkann). Auch auf der Seite von wemakethings steht dazu leider nichts. Ein weiteres Detail ist die runde Spitze auf Sensorseite - diese soll das Einstecken in den Topf erleichtern. Analogie (schlechter Wortwitz inbegriffen): Nein, kein Fieberthermometer, sondern diese Einsteckkärtchen, die man oft in Pflanzkübeln findet. Nach ein paar Stunden Grübeln steht das Layout. Zufrieden ist man natürlich nie, aber es hätte auch schlechter sein können: <gallery> Datei:Chirp_sch.png|Schaltplan des Minichirp Datei:Chirp_brd.png|Layout des Minchirp </gallery> = Aufbau = Der Aufbau ist weitestgehend harmlos. Lediglich an einer Stelle ist es ziemlich eng: das nicht genutzte Eck vom Signalgeber kommt den Pads vom Taster gefährlich nahe und obwohl ich mich beim Footprint des kleinen Lautsprechers an das Datenblatt gehalten habe, scheinen die Pins nicht ganz auf die Pads zu passen. Beim Bestücken sollte man jedoch darauf achten, den Taster vor dem Piepser aufzulöten und den Batteriehalter als allerletztes einzulöten. Zum einen, weil sonst die Lötspitze zu stinken anfängt, zum anderen, weil Piepser und Batteriehalter die klobigsten Komponenten sind und sie dadurch das Löten der anderen Bauteile deutlich erschweren. {{Infobox AVR | Typ = ATtiny44 | Takt = 1 | FuseH = DE | FuseL = E2 }} Zum Flashen muss ein Flachbandkabel an den Konnektor, mit nicht eingelegter Batterie können Fuses und Flash geschrieben werden, zumindest wenn man die passende Hexfile hat. Auf Github liegt sie zumindest nicht, also den Compiler selbst anwerfen. <gallery> Datei:Chirp_asm_top.jpg|Von oben... Datei:Chirp_asm_bot.jpg|...und unten </gallery> = Bedienung = Kurz nachdem die Firmware auf dem Controller gelandet ist, fängt das Teil auch an zu Zirpen. Was ich nicht wusste: wenn nichts im EEPROM steht, wird über die LED auch gleich die Referenzhelligkeit gemessen und abgelegt. Später wird erst ab diesem Wert gezirpt. Grundlegend keine schlechte Idee, nur war zu diesem Zeitpunkt die Schreibtischleuchte perfekt auf die LED ausgerichtet. Im etwas dunkleren Wohnzimmer wurde dann geblinkt statt gezirpt. Also die gerade abgeknipste Leitung wieder anlöten, und den EEPROM löschen. So viel vom ersten Fallstrick bei der Bedienung. Ansonsten ist das Teil einfach zu bedienen: Nach dem ersten Einschalten oder dem Drücken des (Re-)Set-Tasters wird die "Trocken-Feuchtigkeit" gemessen, also jene wenn man die Pflanze gießen sollte. Die Messung wird nach ca. 5 Sekunden mit einem längeren Zirpen quittiert. Anschließend kann man die Pflanze (aber nicht den Chirp) mit Wasser versorgen. Die Elektronik wacht immer wieder auf und misst die Kapazität der Sensorfläche. Wird eine zu niedrige Feuchtigkeit ermittelt, legt bei Helligkeit die zirpende Grille los (nein, nicht [https://www.youtube.com/results?search_query=zirpende+Grille+MIB die]). Bei Dunkelheit wird man durch die LED benachrichtigt. Erkennt der Mikrocontroller, dass die Feuchtigkeit gestiegen ist, wird das Gießen wiederum mit einem länglichen Zirpen bestätigt. Nachdem die erste Woche bei meinen widerstandsfähigeren Topfpflanzen (die für den ersten Test herhalten mussten) vorbei war, wurde ich etwas ungeduldig. Kein Zirpen. Einen Tag später legte sie aber los. Nicht zu laut aber dennoch gut hörbar. Bis jetzt sehr zuverlässig. = Lizenz = Das Originalprojekt ist unter der CERN OHL 1.1 lizenziert. Der Einfachheit halber ziehe ich gleich. = Download = * [[Datei:Chirp.zip|Chirp.zip]] = Wer will? = Es gibt noch ein paar der Leiterkarten. Wer eine will, kann sie gerne kostenlos aber gegen Versandkosten haben. Und nein: ich verkaufe keine fertig bestückten Chirps. Vielleicht übernimmt ja Mic mein Layout und bietet es auf Tindie an!? [[Kategorie:AVR]] 1cd7398b04b7fd873c2be31c59950a5c6b2665e6 Hobbyelektronik.org:Über Hobbyelektronik.org 4 463 1103 2017-05-07T14:40:33Z Chris 2 Weiterleitung nach [[Hobbyelektronik.org:Impressum]] erstellt wikitext text/x-wiki #WEITERLEITUNG [[Hobbyelektronik.org:Impressum]] cf4945afa9e17f9f03ae6f8e3b4b3b8655db4ef6 Hobbyelektronik.org:Datenschutz 4 6 1104 983 2017-05-07T14:40:52Z Chris 2 Weiterleitung nach [[Hobbyelektronik.org:Impressum]] erstellt wikitext text/x-wiki #WEITERLEITUNG [[Hobbyelektronik.org:Impressum]] cf4945afa9e17f9f03ae6f8e3b4b3b8655db4ef6 Hobbyelektronik.org:Impressum 4 4 1105 1052 2017-05-11T20:23:34Z Qsysopr 1 Abschnitt zu Werbung nach oben verschoben. wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - Attribution-NonCommerial-ShareAlike 3.0 (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies richten auf Ihrem Rechner keinen Schaden an und enthalten keine Viren. Cookies dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * Browsertyp/ Browserversion * verwendetes Betriebssystem * Referrer URL * Hostname des zugreifenden Rechners, IP in gekürzter Form * Uhrzeit der Serveranfrage Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Quelle e-recht24.de (angepasst) 759644e123a2cbb1685f017c686f0c29c0e452e8 Datei:Mleddrv brd double.png 6 464 1106 2017-11-12T18:30:35Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mleddrv brd single.png 6 465 1107 2017-11-12T18:30:36Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mleddrv sch.png 6 466 1108 2017-11-12T18:30:36Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mleddrv.jpg 6 467 1109 2017-11-12T18:30:38Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mleddrv.zip 6 468 1110 2017-11-12T18:30:39Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mleddrv Kennlinien.png 6 469 1111 2017-11-12T18:31:55Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Mini-LED-Treiber 0 470 1112 2017-11-12T18:35:01Z Chris 2 Seite erstellt wikitext text/x-wiki [[Datei:mleddrv.jpg|thumb|Aufgebauter LED-Treiber]] Bei der [[Briefkasteninnenbeleuchtung]] habe ich gemerkt, dass ich keine kompakten LED-Treiber herumliegen habe. Zwar ist eine Konstantstromquelle sehr einfach auf Lochraster oder auch fliegend aufgebaut, aber leider ist die Schaltung dann entweder groß oder mechanisch empfindlich. =Funktionsweise= Die Schaltung und die Idee dahinter ist weder kompliziert noch neu. Im Gegenteil dürfte sie sogar ein gutes Beispiel aus dem Lehrbuch sein. <gallery> mleddrv_sch.png|Schaltplan </gallery> Sie wahlweise mit zwei Bipolar-Transistoren oder mit zumindest einem FET aufgebaut werden. Das Prinzip ist wie folgt: steigt die Spannung an der Basis eines Bipolar-Transistors über dessen Basis-Emitter-Spannung, wird dieser gemäß seiner Stromverstärkung zwischen Kollektor und Emitter leitend. Erzeugt man diese Spannung über einen Widerstand, kann man über dessen Wert den Strom definieren, ab dem der Transistor leitend wird. Üblicherweise liegt die U<sub>BE</sub> eines BC548 bei 0,6 V. Möchte man, dass dieser bei 5 mA leitend wird, muss am Widerstand eben diese Spannung abfallen. R = U/I ergibt 120 Ohm. Das ist schon einmal die halbe Miete. Jetzt muss diese Regelgröße nur noch zurückgeführt werden. Hier hilft ein zweiter Transistor, der in Serie zur LED geschalten wird. Der Transistor muss nun so angesteuert werden, dass er, wenn die Spannung (und damit der Strom) am Widerstand höher wird, weniger Strom durchlässt. Spannung hoch: Strom hoch, Spannung runter: Strom runter. Genau das macht unser "Messtransistor", wenn man ihm einen Pull-up am Emitter spendiert. In ein paar Beziehungen kann man die Schaltung verbessern: ersetzt man den "Regeltransistor" durch einen n-Kanal-FET, gewinnt man zwei Dinge: zum einen kann der Pull-up-Widerstand deutlich größer dimensioniert werden: FETs benötigen im Gegensatz zu Bipolar-Transistoren keinen nennenswerten Strom am Gate; zum anderen entfällt die Kollektor-Emitter-Spannung, bzw. wird durch den R<sub>ds,on</sub> ersetzt, welcher sich positiv auf die minimale Betriebsspannung auswirkt. Ferner muss der Pull-up des oberen ("Regel-")Transistors nicht unbedingt direkt an der Versorgung angeschlossen werden, dieser kann zum Schalten der Konstantstromquelle genutzt werden. Da die Stromregelung relativ schnell ist, kann die Leitung problemlos zum Dimmen per PWM genutzt werden. =Layout= Je kleiner, desto besser - allerdings sollte es auch noch per Hand lötbar sein. Deshalb kommen die im SOT-23-Gehäuse verfügbaren Transistoren BSS138 und BC848 zum Einsatz. Bei den Widerständen reichen welche im 0603-Gehäuse. Um den Platz effektiv nutzen zu können, habe ich zwei Varianten erstellt: eine einseitig und beidseitig bestückbare: <gallery> mleddrv_brd_single.png|Einseitit bestücktes Layout mleddrv_brd_double.png|Zweiseitig bestücktes Layout </gallery> =Leistungsfähigkeit= Widerstände 0603-Gehäuse können in aller Regel 100 mW ab. Das klingt nach nicht sehr viel, ist aber für die meisten nicht-High-Power-LEDs gut genug. Wie oben beschrieben, fallen über den Widerstand ca. 0,65 V ab, mit I = P/U ergibt das einen Strom von 154 mA - da kann man schon fast von "High Power" sprechen. Der begrenzende Faktor liegt aber meist woanders. Der "obere" der Transistoren stellt den Strom ein, über ihn fällt somit Spannungsdifferenz zwischen Eingangsspannung und der Vorwärtsspannung der LED sowie den Spannungsabfall über den Messwiderstand ab. Die Leistung in diesem Transistor berechnet sich zu :<math>P = (U - U_\textrm{f} - U_\textrm{BE}) \cdot I_\textrm{LED}</math> Würde man eine weiße LED (U<sub>LED</sub> = ca. 3,2 V) mit 100 mA und einer Eingangsspannung von 12 V treiben wollen, verbrät der Transistor stolze 0,8 Watt. Das wird mit Sicherheit nichts. Im Datenblatt des BSS138 steht eine maximale Leistung von 0,36 Watt und ein Derating von 2,8 mW pro °C. YMMV. Mit diesen Informationen kann man Kennlinienfelder zeichnen - ich hab da schon mal was vorbereitet: <gallery> mleddrv_Kennlinien.png|Kennlinienfeld des LED-Treibers </gallery> Wer das Lesen von Kennlinienfeldern nicht gewohnt ist, hier eine kleine Erläuterung: Zunächst sucht man sich eine Kennlinie aus - für die oben genannte weiße LED wäre das die durchgehend Schwarze. Nun kann man entweder von unten oder links lesen, je nachdem, welchen Wert man sucht. Will man die LED mit 100 mA treiben, sucht man sich auf der Y-Achse die 100, und findet den Schnittpunkt mit der schwarzen Kennlinie. An dieser hangelt man sich nach unten und liest die dazugehörende maximale Betriebsspannung ab: 6,7nochwas Volt. Andersrum: Bei einer Betriebsspannung von 12 V geht man nach oben, wiederum zum Schnittpunkt und dann nach links: irgendwas zwischen 35 und 40 mA. Die Linien im Diagramm sind nicht zufällig gewählt - diese entsprechen in etwa den Vorwärtsspannungen der LEDs in den jeweiligen Farben (schwarz für weiße LEDs, gelbe und orange entsprechen etwa den grünen). Die gestrichelten Linien entsprechen der Reihenschaltung von zwei LEDs der entsprechenden Farbe. Hier sieht man auch, dass durch den höheren Spannungsabfall an den LEDs der Spannungsabfall am Transistor fällt und dadurch höhere Betriebsspannungen möglich werden. Zum Eingangsspannungsbereich kann ich nicht viel sagen, außer dass dieser etwa mindestens so groß wie die LED-Vorwärtsspannung + 0,7 V sein sollte. Das obere Ende wird durch die Transistoren begrenzt. Beim BSS138 wäre das theoretisch die LED-Spannung + 50 Volt. Vorher gibt es aber sicher thermische Probleme. =Download= [[Datei:mleddrv.zip|Schaltplan, Layout, Excel-Datei mit Kennlinienfeld, LtSpice-Daten zum Spielen]] Schaltplan, Layout, Excel-Datei mit Kennlinienfeld, LtSpice-Daten zum Spielen d33c496f9ca1c28347d72ffa3951c14aeb8cdfa9 1114 1112 2018-01-31T20:59:46Z Chris 2 wikitext text/x-wiki [[Datei:mleddrv.jpg|thumb|Aufgebauter LED-Treiber]] Bei der [[Briefkasteninnenbeleuchtung]] habe ich gemerkt, dass ich keine kompakten LED-Treiber herumliegen habe. Zwar ist eine Konstantstromquelle sehr einfach auf Lochraster oder auch fliegend aufgebaut, aber leider ist die Schaltung dann entweder groß oder mechanisch empfindlich. =Funktionsweise= Die Schaltung und die Idee dahinter ist weder kompliziert noch neu. Im Gegenteil dürfte sie sogar ein gutes Beispiel aus dem Lehrbuch sein. <gallery> mleddrv_sch.png|Schaltplan </gallery> Sie wahlweise mit zwei Bipolar-Transistoren oder mit zumindest einem FET aufgebaut werden. Das Prinzip ist wie folgt: steigt die Spannung an der Basis eines Bipolar-Transistors über dessen Basis-Emitter-Spannung, wird dieser gemäß seiner Stromverstärkung zwischen Kollektor und Emitter leitend. Erzeugt man diese Spannung über einen Widerstand, kann man über dessen Wert den Strom definieren, ab dem der Transistor leitend wird. Üblicherweise liegt die U<sub>BE</sub> eines BC548 bei 0,6 V. Möchte man, dass dieser bei 5 mA leitend wird, muss am Widerstand eben diese Spannung abfallen. R = U/I ergibt 120 Ohm. Das ist schon einmal die halbe Miete. Jetzt muss diese Regelgröße nur noch zurückgeführt werden. Hier hilft ein zweiter Transistor, der in Serie zur LED geschalten wird. Der Transistor muss nun so angesteuert werden, dass er, wenn die Spannung (und damit der Strom) am Widerstand höher wird, weniger Strom durchlässt. Spannung hoch: Strom hoch, Spannung runter: Strom runter. Genau das macht unser "Messtransistor", wenn man ihm einen Pull-up am Emitter spendiert. In ein paar Beziehungen kann man die Schaltung verbessern: ersetzt man den "Regeltransistor" durch einen n-Kanal-FET, gewinnt man zwei Dinge: zum einen kann der Pull-up-Widerstand deutlich größer dimensioniert werden: FETs benötigen im Gegensatz zu Bipolar-Transistoren keinen nennenswerten Strom am Gate; zum anderen entfällt die Kollektor-Emitter-Spannung, bzw. wird durch den R<sub>ds,on</sub> ersetzt, welcher sich positiv auf die minimale Betriebsspannung auswirkt. Ferner muss der Pull-up des oberen ("Regel-")Transistors nicht unbedingt direkt an der Versorgung angeschlossen werden, dieser kann zum Schalten der Konstantstromquelle genutzt werden. Da die Stromregelung relativ schnell ist, kann die Leitung problemlos zum Dimmen per PWM genutzt werden. =Layout= Je kleiner, desto besser - allerdings sollte es auch noch per Hand lötbar sein. Deshalb kommen die im SOT-23-Gehäuse verfügbaren Transistoren BSS138 und BC848 zum Einsatz. Bei den Widerständen reichen welche im 0603-Gehäuse. Um den Platz effektiv nutzen zu können, habe ich zwei Varianten erstellt: eine einseitig und beidseitig bestückbare: <gallery> mleddrv_brd_single.png|Einseitit bestücktes Layout mleddrv_brd_double.png|Zweiseitig bestücktes Layout </gallery> =Leistungsfähigkeit= Widerstände 0603-Gehäuse können in aller Regel 100 mW ab. Das klingt nach nicht sehr viel, ist aber für die meisten nicht-High-Power-LEDs gut genug. Wie oben beschrieben, fallen über den Widerstand ca. 0,65 V ab, mit I = P/U ergibt das einen Strom von 154 mA - da kann man schon fast von "High Power" sprechen. Der begrenzende Faktor liegt aber meist woanders. Der "obere" der Transistoren stellt den Strom ein, über ihn fällt somit Spannungsdifferenz zwischen Eingangsspannung und der Vorwärtsspannung der LED sowie den Spannungsabfall über den Messwiderstand ab. Die Leistung in diesem Transistor berechnet sich zu :<math>P = (U - U_\textrm{f} - U_\textrm{BE}) \cdot I_\textrm{LED}</math> Würde man eine weiße LED (U<sub>LED</sub> = ca. 3,2 V) mit 100 mA und einer Eingangsspannung von 12 V treiben wollen, verbrät der Transistor stolze 0,8 Watt. Das wird mit Sicherheit nichts. Im Datenblatt des BSS138 steht eine maximale Leistung von 0,36 Watt und ein Derating von 2,8 mW pro °C. YMMV. Mit diesen Informationen kann man Kennlinienfelder zeichnen - ich hab da schon mal was vorbereitet: <gallery> mleddrv_Kennlinien.png|Kennlinienfeld des LED-Treibers </gallery> Wer das Lesen von Kennlinienfeldern nicht gewohnt ist, hier eine kleine Erläuterung: Zunächst sucht man sich eine Kennlinie aus - für die oben genannte weiße LED wäre das die durchgehend Schwarze. Nun kann man entweder von unten oder links lesen, je nachdem, welchen Wert man sucht. Will man die LED mit 100 mA treiben, sucht man sich auf der Y-Achse die 100, und findet den Schnittpunkt mit der schwarzen Kennlinie. An dieser hangelt man sich nach unten und liest die dazugehörende maximale Betriebsspannung ab: 6,7nochwas Volt. Andersrum: Bei einer Betriebsspannung von 12 V geht man nach oben, wiederum zum Schnittpunkt und dann nach links: irgendwas zwischen 35 und 40 mA. Die Linien im Diagramm sind nicht zufällig gewählt - diese entsprechen in etwa den Vorwärtsspannungen der LEDs in den jeweiligen Farben (schwarz für weiße LEDs, gelbe und orange entsprechen etwa den grünen). Die gestrichelten Linien entsprechen der Reihenschaltung von zwei LEDs der entsprechenden Farbe. Hier sieht man auch, dass durch den höheren Spannungsabfall an den LEDs der Spannungsabfall am Transistor fällt und dadurch höhere Betriebsspannungen möglich werden. Zum Eingangsspannungsbereich kann ich nicht viel sagen, außer dass dieser etwa mindestens so groß wie die LED-Vorwärtsspannung + 0,7 V sein sollte. Das obere Ende wird durch die Transistoren begrenzt. Beim BSS138 wäre das theoretisch die LED-Spannung + 50 Volt. Vorher gibt es aber sicher thermische Probleme. =Download= [[Datei:mleddrv.zip|Schaltplan, Layout, Excel-Datei mit Kennlinienfeld, LtSpice-Daten zum Spielen]] Schaltplan, Layout, Excel-Datei mit Kennlinienfeld, LtSpice-Daten zum Spielen [[Kategorie:Elektronik]] [[Kategorie:Kleine Helferlein]] c40fbce377ddb635f5b1be8f6213d8c30c1f09c1 Datei:Pirozeda gehaeuse3.jpg 6 471 1115 2018-04-15T19:49:54Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda size.jpg 6 472 1116 2018-04-15T19:49:56Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda brd.png 6 473 1117 2018-04-15T19:49:57Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda currdata display.png 6 474 1118 2018-04-15T19:49:58Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda currdata plot.png 6 475 1119 2018-04-15T19:49:59Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda debug.png 6 476 1120 2018-04-15T19:49:59Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda heatmap.png 6 477 1121 2018-04-15T19:50:01Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda histdata plot.png 6 478 1122 2018-04-15T19:50:01Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda livetrace.png 6 479 1123 2018-04-15T19:50:02Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda sch.png 6 480 1124 2018-04-15T19:50:03Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda fixed top.jpg 6 481 1125 2018-04-15T19:50:05Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda flashing.jpg 6 482 1126 2018-04-15T19:50:07Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda front.jpg 6 483 1127 2018-04-15T19:50:08Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda gehaeuse.jpg 6 484 1128 2018-04-15T19:50:10Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda gehaeuse2.jpg 6 485 1129 2018-04-15T19:50:11Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda.zip 6 486 1130 2018-04-15T19:50:23Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Pirozeda 0 487 1131 2018-04-15T19:50:58Z Chris 2 Seite erstellt wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich, was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1np |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || X7R-G0603 220p |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite auf der Seite des Adapters direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C4 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC4:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] c5c262221fe7ec1f35e6ed880c621a7df1dc3b14 1135 1131 2018-04-15T19:58:51Z Chris 2 /* Bitbanging */ wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1np |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || X7R-G0603 220p |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite auf der Seite des Adapters direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C4 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC4:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] b77371026c4bdccffc921a0a725a1a89bf37d621 1136 1135 2018-04-15T20:02:23Z Chris 2 /* Hardware */ wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1np |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || X7R-G0603 220p |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite auf der Seite des Adapters direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C4 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC4:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] 8a3bd50071119cac4c06e35de8b90ba00cc4d8e7 1137 1136 2018-04-15T20:03:51Z Chris 2 /* Hardware */ wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1np |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || X7R-G0603 220p |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C4 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC4:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] 934d3193cb702b78b9615c4ffb953c01efe9a483 Datei:Sungo sxlplus ctrl top.jpg 6 488 1138 2018-04-16T20:12:33Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Sungo sxlplus pwr bot.jpg 6 489 1139 2018-04-16T20:12:36Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Sungo sxlplus pwr port.jpg 6 490 1140 2018-04-16T20:12:38Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Sungo sxlplus pwr switch.jpg 6 491 1141 2018-04-16T20:12:40Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Sungo sxlplus pwr top.jpg 6 492 1142 2018-04-16T20:12:43Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Sungo sxlplus.JPG 6 493 1143 2018-04-16T20:12:45Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Sungo sxlplus ctrl bot.jpg 6 494 1144 2018-04-16T20:12:47Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Prozeda-Decoder 0 460 1146 1145 2018-04-16T20:14:50Z Chris 2 /* Einblick in den Regler */ wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FTDI2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Einblick in den Regler= Ein Griff in die Zukunft - 11/2017: Im Rahmen der [[Pirozeda]]-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen: <gallery> sungo_sxlplus.JPG | SUNGO SXLplus von außen sungo_sxlplus_ctrl_top.jpg | Controllerboard vorne sungo_sxlplus_ctrl_bot.jpg | Controllerboard hinten sungo_sxlplus_pwr_top.jpg | Leistungsboard vorne sungo_sxlplus_pwr_bot.jpg | Leistungsboard hinten sungo_sxlplus_pwr_port.jpg | Anschluss des Datasticks sungo_sxlplus_pwr_switch.jpg | Schaltmodule </gallery> ==Controllerboard== Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte. Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war. Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt. Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt... ==Leistungsboard== So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen. Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter. Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder. Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können. =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <source lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </source> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <source lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </source> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <source lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </source> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <source lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </source> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] db4b97c42baf33040cc613ba2e34506f1e51c528 1148 1146 2018-04-19T19:57:00Z Chris 2 wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FT2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Einblick in den Regler= Ein Griff in die Zukunft - 11/2017: Im Rahmen der [[Pirozeda]]-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen: <gallery> sungo_sxlplus.JPG | SUNGO SXLplus von außen sungo_sxlplus_ctrl_top.jpg | Controllerboard vorne sungo_sxlplus_ctrl_bot.jpg | Controllerboard hinten sungo_sxlplus_pwr_top.jpg | Leistungsboard vorne sungo_sxlplus_pwr_bot.jpg | Leistungsboard hinten sungo_sxlplus_pwr_port.jpg | Anschluss des Datasticks sungo_sxlplus_pwr_switch.jpg | Schaltmodule </gallery> ==Controllerboard== Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte. Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war. Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt. Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt... ==Leistungsboard== So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen. Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter. Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder. Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können. =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <source lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </source> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <source lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </source> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <source lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </source> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <source lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </source> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] 324a37a0697d8363ead77401ce7fc96cc7ad0f1f Hauptseite 0 1 1147 1134 2018-04-16T20:17:12Z Chris 2 Änderungen aktualisiert wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet ==Änderungen== *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. 41d66c6de8395e82e09bc9ba7181c87db1946ed7 1161 1147 2018-08-05T20:43:39Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet ==Änderungen== *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. 374feda126f2aed7157e0c5a08b42c81c8ae209d 1168 1161 2018-08-19T21:01:48Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle] exportieren *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden ==Änderungen== *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. 7b9f00c3ca973b7be3534c081f40b5715c4d16f6 1170 1168 2018-08-19T21:04:44Z Chris 2 und natürlich wieder ein Typo wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden ==Änderungen== *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. ba87da15d320893ea105393fd29f17f783cdd354 1189 1170 2018-08-23T21:00:17Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] ==Änderungen== *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. a644b4765994cf515d27b14b228390875f2f69ea 1195 1189 2018-08-27T20:31:00Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] ==Änderungen== *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. 9734f55b4e2b1ea98110eb17a4ba75328e58d9b0 Pirozeda 0 487 1149 1137 2018-04-25T16:26:43Z Chris 2 fuses korrigiert wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1np |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || X7R-G0603 220p |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] 181be098b745dce5050455e647deabff9707ad80 1159 1149 2018-08-05T20:40:34Z Chris 2 /* Download */ Version 0.3 wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1np |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || X7R-G0603 220p |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] 9cec4d9206870de59dc79bdeb4b746d9d4f47493 1160 1159 2018-08-05T20:41:09Z Chris 2 /* Änderungen */ Close-Tag für Galerie vergessen wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1np |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || X7R-G0603 220p |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] 9427151ec75830acff588505c18b3c00bcc0a239 1162 1160 2018-08-05T20:44:28Z Chris 2 /* 2018-08-05: Version 0.3 */ wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1np |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || X7R-G0603 220p |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] b70c2996a78511c7261c2b8a03f0d02ec8299d13 1194 1162 2018-08-27T19:34:23Z Chris 2 /* Änderungen */ wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1np |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || X7R-G0603 220p |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] 57f658b8dfd4a4ceddd9f78f68d156b477ad32e4 Hobbyelektronik.org:Impressum 4 4 1150 1105 2018-05-20T21:11:55Z Chris 2 Infos zur Kommentarfunktion wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - Attribution-NonCommerial-ShareAlike 3.0 (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies richten auf Ihrem Rechner keinen Schaden an und enthalten keine Viren. Cookies dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * Browsertyp/Browserversion * verwendetes Betriebssystem * Referrer URL * Hostname des zugreifenden Rechners, IP-Adresse (gekürzt) * Uhrzeit der Serveranfrage Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Spam, unrechtmäßigen Aussagen und Texten und der Wahrung eines gewissen Niveaus findet eine Moderation statt. Zu diesem Zweck werden zusätzlich zu den über das Formular eingegebene Angaben folgende Informationen dauerhaft gespeichert: * IP-Adresse (ungekürzt) * Datum und Uhrzeit * Browsertyp/Browserversion Quelle e-recht24.de (angepasst) 56c0a548b9aa853f16cac5a5da3c4d53271bbe61 1151 1150 2018-05-20T21:20:18Z Chris 2 wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - Attribution-NonCommerial-ShareAlike 3.0 (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies richten auf Ihrem Rechner keinen Schaden an und enthalten keine Viren. Cookies dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * Browsertyp/Browserversion * verwendetes Betriebssystem * Referrer URL * Hostname des zugreifenden Rechners, IP-Adresse (gekürzt) * Uhrzeit der Serveranfrage Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Spam, unrechtmäßigen Aussagen und Texten und der Wahrung eines gewissen Niveaus findet eine Moderation statt. Zu diesem Zweck werden zusätzlich zu den über das Formular eingegebene Angaben folgende Informationen dauerhaft gespeichert: * IP-Adresse (ungekürzt) * Datum und Uhrzeit * Browsertyp/Browserversion Quelle e-recht24.de (angepasst) 887bf0c878ce9b8642afd8e66f3d332513b3f089 1152 1151 2018-05-21T14:44:59Z Chris 2 wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - Attribution-NonCommerial-ShareAlike 3.0 (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies richten auf Ihrem Rechner keinen Schaden an und enthalten keine Viren. Cookies dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * Browsertyp/Browserversion * verwendetes Betriebssystem * Referrer URL * Hostname des zugreifenden Rechners, IP-Adresse * Uhrzeit der Serveranfrage Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Spam, unrechtmäßigen Aussagen und Texten und der Wahrung eines gewissen Niveaus findet eine Moderation statt. Zu diesem Zweck werden zusätzlich zu den über das Formular eingegebene Angaben folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion Quelle e-recht24.de (angepasst) 643307c9815304519ba2efa6fd71dd9850645a03 1153 1152 2018-05-25T19:23:16Z Chris 2 ein bisschen mehr zur Datenerhebung und Datenschutz wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS1.2 ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) aa02e8d290267d01f3e6664a5ccac6ef8a5220d7 Lichtsensor Avago APDS-9300 0 428 1154 1029 2018-05-27T19:45:36Z Chris 2 /* Software - der erste Versuch */ Link korrigiert (verweist nun auf die wayback machine) wikitext text/x-wiki Vor einiger Zeit (genau genommen noch im Studium) wollte ich mit Lichtsensoren (ambient light sensors, ALS) spielen. Da ich bei Farnell bestellen konnte, kamen zwei Avago APDS-9300 mit auf das Bestellformular (Mittlerweile auch beim blauen Claus bzw. Völkner zu haben). Aufgrund der Bauform und Zeitmangel blieben sie relativ lange in der ESD-Tüte. =Der Sensor= Was soll man groß Worte über einen Lichtsensor verschwenden? Licht rein, aufbereitetes Signal raus und gut ist. Ganz so einfach ist es (zumindest beim APDS-9300) leider nicht. Viele optische Sensoren drehen bei Infrarot wild, das menschliche Auge zeichnet sich dagegen als ziemlich unempfindlich aus. In Digitalkameras werden aus diesem Grund IR-Filter verbaut (die Astrofotografen wieder entfernen), allerdings scheint das den Entwicklern bei Avago entweder zu teuer oder zu unpraktisch gewesen zu sein - sie haben zwei Fotodioden verbaut: Eine ist empfindlich auf das sichtbare Licht und Infrarot, die andere nur auf Infrarot (siehe Seite 7 vom Datenblatt). Der Rest ist Mathematik. Da die menschliche Wahrnehmung weitestgehend logarithmisch ist, braucht man zur Nachbildung einen großen Dynamikumfang. Daher kann der ALS mehrere Betriebsmodi. Zum einen kann man die Integrationszeit (also die Zeit, in der die Lichtdosis gesammelt wird) wählen - konkret zwischen 13,7 ms, 101 ms und 402 ms. Zum anderen kann man einen 16-fach-Verstärker zuschalten. Dadurch gewinnt man zwar Empfindlichkeit, bezahlt die aber mit der Auflösung und Rauschen. Die Wahl der richtigen Einstellung hängt selbstverständlich von der Umgebungshelligkeit ab, ansonsten liest man entweder 0 oder der bekommt Werte in der Sättigung, die einfach keinen Sinn ergeben. =Hardware= Bei der Fertigung meiner ersten Fuhre Leiterkarten bei DirtyPCBs landete auch ein kleines Breakout-Board auf dem Panel: <gallery> Datei:apds9300_sch.png|Schaltplan, Datei:apds9300_brd.png|Layout Datei:apds9300_asy.jpg|und aufgebautes Sensormodul </gallery> Neben dem Sensor selbst befindet sich aufgrund dessen etwas unpraktischen Versorgungsspannung ein 2,5 V-LDO-Spannungsregler. Die Wahl auf den LDO fiel, damit die Schaltung neben den eher altmodischen 5 V auch bei 3,3 V (und somit zum Beispiel mit dem Raspberry Pi) funktioniert. Als Schnittstelle dient bei dem Lichtsensor I²C, die Treiberstufen sind hier zwar zwangsläufig Open Drain und können deshalb in aller Regel etwas höhere Spannungen als die Betriebsspannung ab, bei den Eingangstufen bzw. ESD-Schutz wird es für das Bauteil bei höheren Spannungen ungemütlicher. ==Levelshifter== Damit man den I²C mit höherer Spannung betreiben kann, wird ein (bzw. eher zwei) Levelshifter benötigt. Diesen kann man entweder fertig kaufen oder mit nur wenigen Bauteilen aufbauen - [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] erklärt, wie es funktioniert. Für alle, die zu faul zum Klicken oder des Englischen nicht ganz so mächtig sind: Bei der Schaltung wird sowohl die Body-Diode als auch die schaltende Wirkung des FET genutzt (und als Beifang die Pull-Up-Widerstände, die man für I²C eh braucht). Das Schaltungsprinzip ist einfach wie genial: Wird keine der beiden Seiten auf Masse gezogen, ist U_GS nahezu 0 oder zumindest weit unter U_GS,th - der FET sperrt und dadurch dass die Spannung auf der Kathoden-Seite der Diode höher als auf der Anoden-Seite ist, sehen sich die Schaltungsteile nicht. Den Rest erledigen die Pull-ups. Wird auf der 3,3 V-Seite das Signal auf Masse gezogen, steigt U_GS über U_GS,th und der Transistor beginnt zu leiten. Dadurch sieht man auf der 5 V-Seite die Masse der 3,3 V-Seite. Szenario Nummer 3 ist nicht ganz so offensichtlich: Wird die 5 V-Seite auf Masse gezogen, fällt zunächst der Drain-Pin des FETs auf Masse. Jetzt kommt ein Teil vom Transistor ins Spiel, der einem manchmal einen Knoten ins Gehirn macht: Die Body-Diode. Ist auf deren Kathoden-Seite ein niedrigeres Potenzial als auf deren Anoden-Seite, wird sie leitfähig, somit zieht sie den Source-Pin ebenfalls gegen die Masse, die auf der Source-Seite anliegt. Gegen - nicht auf - da noch ein bisschen Vorwärtsspannung abfällt. Allerdings fällt steigt auch U_GS über U_GS,th (der zweite Knoten im Gehirn) und der FET wird leitfähig. Somit ist die Masse der 5 V-Seite auf der 3,3 V-Seite (relativ) sauber sichtbar. Fertig ist der pillepalle einfache bidirektionale Levelshifter. Einziger Nachteil: die Spannung "links" muss immer kleiner sein als die "rechts". Zudem ist man mit den Spannungspegeln begrenzt (zum einen durch U_GS,th des FET und zum anderen durch die U_f der Body-Diode). Übrigens kann man durch das Abklemmen des Gates die Seite mit der niedrigeren Spannung isolieren. =Software - der erste Versuch= Wie kann man relativ einfach mit I²C basteln? Bei denen im PC kommt man zumindest unter Windows nicht ran (und will es [https://web.archive.org/web/20160506154718/http://www.paintyourdragon.com/?p=43 vermutlich auch nicht]), bei Mikrocontrollern muss man erst Soft- und Hardware basteln - das ist aufwändig und fehleranfällig. Was liegt also näher, als den Raspberry Pi zu verwenden? Dort gibt es neben den [https://github.com/groeck/i2c-tools i2c-tools] auch eine Integration in Python. Da ich keine besonderen Erfahrungen mit letztere Sprache habe, möge man mir die Codequalität entschuldigen. apds9300.py ist eine Klasse, die die Kommunikation mit dem Sensor beinhaltet. Mit viewapds.py wird der Sensor im Halbsekunden-Takt ausgelesen und sowohl die rohen als auch der berechnete Wert ausgegeben. So viel zur Theorie. In der Praxis verwandelte sich die Verwunderung sehr schnell in Verzweiflung - es kamen einfach keine auch nur halbwegs sinnvollen Werte heraus. Zuerst hatte ich meine kläglichen Versuche in Python im Verdacht, nach mehrmaligem Überprüfen und neu schreiben stellte sich allerdings heraus, dass anscheinend etwas mit dem Chip oder Datenblatt nicht passt, denn ein Vergleich mit [[wpde:Lux_(Einheit)#Beispiele_typischer_Beleuchtungsst.C3.A4rken typischen Werten|Beispielen]] in Wikipedia sagte mir nur: du liegst falsch. Nach ein paar Recherchen stellte sich heraus, dass der APDS-9300 auf einem anderen Sensor basiert (oder zumindest nicht verleugenbare Ähnlichkeiten besitzt), dem TS256x von TAOS. Auch der physische Aufbau hat gewisse Ähnlichkeiten (und die Formeln zur Berechnung der Helligkeit ebenfalls). Zudem hatten auch schon andere das Problem mit den Berechnungen, nur gab es keine Lösung. =Kalibrierung= Da hilft nur noch eines: Kalibrieren. Nur gegen was? Die Helligkeitswerte aus dem oben erwähnten Wikipedia-Artikel kann man nicht so einfach und vor allem nicht so genau nachstellen, also muss entweder eine kalibrierte Lichtquelle her oder Vergleichsmessungen gemacht werden. Es liegen ja genügend "Messgeräte" in Form von Handy und Tablet herum. Mit einer [https://play.google.com/store/apps/details?id=com.notquitethem.android.luxmeter passenden App] bekommt man die Helligkeit mundgerecht angezeigt, nur: bei meinen HTC (Sensation, Flyer und [http://hobbyelektronik.org/b/2013/02/transplantation-geglueckt-patient-muss-sterben/ Explorer]) kann man nur zwischen heller Sommertag, bedeckter Sommertag und Zappenduster unterscheiden. Das LG-Handy war in der interessanten Zeit in Reparatur und das Samsung-Tablet hatte zwar eine sehr hohe Auflösung aber dafür eine völlig unbrauchbare Winkelabhängigkeit. Ich habe mir sogar überlegt, mit der Fotokamera zu messen. Aber wie zum Henker kommt man von Blende, Belichtungszeit, Bildempfindlichkeit und Bildausschnitt auf einen brauchbaren Helligkeitswert in Lux? Nachdem die Granularität durch die festen Schritte bei den drei ersten Parametern recht schlecht ist und die Messung durch den Bildausschnitt noch heikler wird, habe ich es bei der Idee belassen. Es muss also ein geeignetes Messgerät her. Nur für das Vermessen eines Sensors Messequipment kaufen (das den Sensor auch gleich ersetzt)? Muss nicht sein: ==Minolta T-10== In der Arbeit ist u. a. ein portables Luxmeter vorhanden und ich durfte es mir freundlicherweise für zwei Wochenenden ausleihen. Das Teil hat eine RS-232-Schnittstelle, wenn auch mit einem etwas komischen Stecker. Nach der Protokollbeschreibung muss man etwas suchen, allerdings ist die Implementierung (abgesehen vom etwas verschwurbelten Ausgabeformat) relativ einfach zu bewerkstelligen. Wer in die Verlegenheit kommt, so ein T-10 (oder vergleichbare Modelle) auszulesen: unten in den Downloads gibt es sowohl für Python als auch C# Quelltexte. ==Versuch 1== Der Messaufbau umfasst: * ALS und Luxmeter (über USB-RS232-Wandler) am Pi * eine windig zusammengebaute Lichtquelle aus LED-Streifen, Kühlkörper und Diffusor aus einem alten Notebook-Display. * Ein Rigol DP832 als Spannungsquelle * Eine Metallschiene sowie ein Pappkarton zum Aufbauen eines "Lichtgalgen" Beide Lichtsensoren (Minolta und mein Kalibrierkandidat) wurden auf gleiche Ebene gebracht (wichtig!) und fixiert. Das Netzteil kann Spannungs- und Stromsweeps, die für solch einen Zweck auf den ersten Blick perfekt geeignet sind. Also den Strom von 0 bis IIRC knapp 1,5 A in 400 Schritten zu je 2 Sekunden durchlaufen lassen, das Messgerät und Sensor mit etwas höherer Frequenz abfragen und in eine Log schreiben lassen. Das Ganze mit allen möglichen Konfigurationen des ALS. Excel auf dem großen PC macht den Rest. Naja, denkste. Die Helligkeit ging alles andere als linear hoch. Die Daten habe ich direkt weggeworfen und die Messung erneut mit Variation Spannung laufen lassen - entgegen dem allgemeinen Glauben ging die Helligkeit linear hoch. Trotzdem ist und bleibt die Regel: LEDs über Stromquellen versorgen. Die Gründe breite ich hier jetzt nicht aus. Dort die beiden Helligkeitswerte im X-Y-Diagramm auftragen lassen und feststellen, dass der Sensor fernab von dem ist, was zu erwarten ist. Genauso sind die Daten in der Hinsicht etwas ungeschickt zum Auswerten, dass es für jede tatsächliche Helligkeit mehrere Wertepaare gibt. Gleichzeitig gibt es aber auch (erwartungsgemäß) ungültige Wertpaare, da ein Sensor vor und der andere nach dem Umschalten der Spannung ausgelesen wurde. Die ganzen Messartefakte kann man zwar filtern, aber das ist unnötig und nervig. Nachdem die ganzen Messungen durch waren, musste das Luxmeter auch schon wieder zurück in die Arbeit. Nachdem der erste Lauf vielversprechend war, glaube ich, dass die anderen Messungen ok waren. Zudem war es viel zu heiß (Sommer 2015), um im Büro zu sitzen. Long story short: ein kleiner Programmierfehler und die Integrationszeiten wurden nicht in den Sensor geschrieben. <gallery> Datei:apds9300_diag_1_1.png|Verstärkung = 1; Integrationszeit = 13,7ms Datei:apds9300_diag_1_2.png|Verstärkung = 16; Integrationszeit = 13,7ms </gallery> Aarrgghh! ==Versuch 2== Fehler darf man machen, solange man daraus lernt. Das Rigol kann USB, und für das Auslesen des ALS habe ich eine Schaltung mit dem [http://hobbyelektronik.org/b/2015/09/mcp2221/ MCP2221] aufgebaut. Die Lichtquelle bleibt die selbe, sie steckt aber nun in der Decke eines Schuhkartons. Dadurch kann der Abstand, Position und Helligkeit (Streulicht!) relativ gut definiert werden: <gallery> Datei:apds9300_box.jpg|Aufbau der Messbox </gallery> Software: Dieses Mal in C#. Das kenne ich halbwegs und mag es. ===Automatisierung=== Zur Ansteuerung vom Netzteil muss erst einmal [https://www.ni.com/visa/ NI VISA] installiert werden. Ich hasse es, ich liebe es. Ich hasse es, weil die VISA-Treiber ein riesiges Bollwerk sind und man beim ersten Versuch immer die falschen erwischt. Zudem gibt es einen schönen Bug, bei dem Windows nach deren Installation irgendwann anfängt, knapp 20 Minuten für den Login zu braucht. Den [http://digital.ni.com/public.nsf/allkb/814FEF952915137686257B6B006C5F4F?OpenDocument offiziellen Fix] habe ich selbst noch nicht getestet, mit der im [http://forums.ni.com/t5/LabVIEW/Issues-with-windows-7-after-Labview-2012-installation/m-p/2257858#M715816 NI-Forum] beschriebenen Vorgehensweise habe ich gute Erfahrungen gemacht. Dadurch macht man sich unter Umständen zwar [[wpde:LAN eXtensions for Instrumentation|LXI]] kaputt, was in den meisten Fällen eh nicht verwendet wird. Was ich an VISA liebe? [[wpde:SCPI|SCPI]]! Messautomatisierung ist etwas wirklich feines und nicht nur, weil man auf dem Weg in die Mittagspause noch kurz "MAHLZEIT" auf dem Multimeter anzeigen lassen kann. Mir hat es in der Arbeit bereits unbeschreiblich viel manuelle Messzeit erspart. Dazu kommt, dass die Wiederholbarkeit sehr gut ist. Wie auch immer, die Software ist schnell und hässlich - aber zweckmäßig - runtergerissen. Die Messungen sind zum Einstellen der Helligkeit der Lichtquelle synchronisiert und neben den deutlich besseren Ergebnissen kann ich zugleich meine Lichtquelle kalibrieren. Ein Messlauf dauert nicht ganz zwei Minuten, wegen der unterschiedlichen Integrationszeiten und den beiden möglichen Verstärkungsfaktoren mal 6 und schon hat man einen Sensor vermessen. ==Auswertung== Das ganze nochmal in Excel verwurstet und es sieht gar nicht mal so gut aus: <gallery> Datei:apds9300_diag_2_1.png|Messergebnisse 1. Sensor mit Gain = 1 Datei:apds9300_diag_2_2.png|Messergebnisse 1. Sensor mit Gain = 16 </gallery> Im ersten Diagramm sieht man, dass die Werte schön und nahezu linear nach oben gehen, allerdings ist da - je nach Integrationslänge ordentlich Faktor drauf. Bei der Ausgabe wurde die Integrationszeit nicht berücksichtigt. Die Einbrüche im zweiten Diagramm lassen sich durch die tatsächlichen Messwerte erklären: <gallery> Datei:apds9300_diag_2_3.png|Messwerte ohne und 16-facher Verstärkung </gallery> Kanal 0 geht bei 16-facher Verstärkung sehr früh in Sättigung - das ist alles. Ok, nun müssen die Helligkeitswerte noch richtig skaliert werden. Meine Vermutung geht stark in die Richtung, dass entweder die Lichtempfindlichkeit oder die Integrationszeit bei den Sensoren nicht ganz richtig sind. Man kann den Korrekturfaktor zwar auf die berechnete Helligkeit anwenden - dadurch dass es in den Berechnungen keine Offsets gibt, sollte das auch funktionieren. Mir ist es allerdings deutlich lieber, direkt die rohen Werte zu behandeln. Also die Messwerte skalieren, durch die Formel zur Berechnung der Helligkeit jagen und das Ergebnis vergleichen. Excel kann das relativ gut automatisch - mit der Zielwertsuche. Der Parameter dafür ist die prozentuale Abweichung der berechneten Helligkeit und der Referenzmessung vom Luxmeter. Damit das Ganze funktioniert, muss der Algorithmus zur Berechnung in Excel implementiert werden. Ich habe aufgehört zu zählen... Unter Berücksichtigung der Integrationszeiten ergibt sich ein Faktor von relativ genau 0,2, um auf die "richtige" Helligkeit zu kommen. Zum Vermessen des zweiten Sensors habe ich diesen Faktor für die Berechnung des ausgegebenen Wertes in meine Software eingetragen und es kommt relativ gut hin - über den kompletten Messbereich war die Abweichung nicht größer als 5 %. Selbstverständlich ist das statistisch nicht aussagekräftig aber trotzdem eine Bestätigung, dass die ganze Aktion nicht grob falsch war. Die Erkenntnisse sind auch direkt in die C#-Software gewandert. Mit dieser kann im aktuellen Zustand die Helligkeit angezeigt werden. ="Kalibrierung" der Lichtquelle= Das Luxmeter musste ich selbstverständlich zurückgeben, aber was nun, wenn plötzlich und völlig unerwartet wieder ein Lichtsensor auf dem Tisch liegt und getestet werden muss, ob er richtig liegt, wenn das Licht angeht? Warum nicht einfach schauen, wie stabil die Lichtquelle ist? Natürlich ist der 15-Minuten-Aufbau nichts, was man für professionelle Zwecke auch nur in Erwägung ziehen würde, aber für den Heimbedarf - und um einen groben Anhaltspunkt zu finden: warum nicht? LEDs verändern sich in ihrem Leben. Wie sie bei Umgebungstemperatur altern: da habe ich kein wirkliches Gefühl. Allerdings weiß ich sehr genau, dass sie mit der Betriebszeit und durch Temperatur altern. Zugleich können sie ihre momentane Ausbeuten durch Erwärmung verändern. Da der Aufbau vermutlich nur für kurze Tests verwendet werden soll, kann die "Abnutzung" durch Betriebsdauer vernachlässigt werden. Anders ist es bei der Veränderung durch Betriebstemperatur. Allerdings kann man das relativ einfach testen: LEDs auf maximaler Leistung betrieben, Lichtsensor darunter packen und während den laufenden Messungen warten. Nach gut 20 Minuten (Länger ist das Ding wahrscheinlich eh nie am Stück im Betrieb) tat sich: nichts. Die LEDs sind offensichtlich stabil genug - oder die Messeinrichtung zu ungenau. Wer weiß. Auf jeden Fall habe ich jetzt eine zumindest grob brauchbare Ergebnisse, falls mal wieder ein Sensor vermessen werden will. =Leiterkarten= Ein paar der oben gezeigten Leiterkarte sind noch übrig. Wer will, kann eine haben. =Downloads= * [[Datei:apds9300.zip]] Alle Sourcen und Messdaten samt Auswertung. [[Kategorie:Elektronik]] [[Kategorie:PC]] [[Kategorie:Sensor]] 51f50053948453ceb58724ca1d99a474ad51badc Mini-LED-Treiber 0 470 1155 1114 2018-07-15T21:23:08Z Chris 2 Typos korrigiert wikitext text/x-wiki [[Datei:mleddrv.jpg|thumb|Aufgebauter LED-Treiber]] Bei der [[Briefkasteninnenbeleuchtung]] habe ich gemerkt, dass ich keine kompakten LED-Treiber herumliegen habe. Zwar ist eine Konstantstromquelle sehr einfach auf Lochraster oder auch fliegend aufgebaut, aber leider ist die Schaltung dann entweder groß oder mechanisch empfindlich. =Funktionsweise= Die Schaltung und die Idee dahinter ist weder kompliziert noch neu. Im Gegenteil dürfte sie sogar ein gutes Beispiel aus dem Lehrbuch sein. <gallery> mleddrv_sch.png|Schaltplan </gallery> Sie kann wahlweise mit zwei Bipolar-Transistoren oder mit zumindest einem FET aufgebaut werden. Das Prinzip ist wie folgt: steigt die Spannung an der Basis eines Bipolar-Transistors über dessen Basis-Emitter-Spannung, wird dieser gemäß seiner Stromverstärkung zwischen Kollektor und Emitter leitend. Erzeugt man diese Spannung über einen Widerstand, kann man über dessen Wert den Strom definieren, ab dem der Transistor leitend wird. Üblicherweise liegt die U<sub>BE</sub> eines BC548 bei 0,6 V. Möchte man, dass dieser bei 5 mA leitend wird, muss am Widerstand eben diese Spannung abfallen. R = U/I ergibt 120 Ohm. Das ist schon einmal die halbe Miete. Jetzt muss diese Regelgröße nur noch zurückgeführt werden. Hier hilft ein zweiter Transistor, der in Serie zur LED geschalten wird. Der Transistor muss nun so angesteuert werden, dass er, wenn die Spannung (und damit der Strom) am Widerstand höher wird, weniger Strom durchlässt. Spannung hoch: Strom hoch, Spannung runter: Strom runter. Genau das macht unser "Messtransistor", wenn man ihm einen Pull-up am Emitter spendiert. In ein paar Beziehungen kann man die Schaltung verbessern: ersetzt man den "Regeltransistor" durch einen n-Kanal-FET, gewinnt man zwei Dinge: zum einen kann der Pull-up-Widerstand deutlich größer dimensioniert werden: FETs benötigen im Gegensatz zu Bipolar-Transistoren keinen nennenswerten Strom am Gate; zum anderen entfällt die Kollektor-Emitter-Spannung, bzw. wird durch den R<sub>ds,on</sub> des FET ersetzt, was sich positiv auf die minimale Betriebsspannung auswirkt. Ferner muss der Pull-up des oberen ("Regel-")Transistors nicht unbedingt direkt an der Versorgung angeschlossen werden, dieser kann zum Schalten der Konstantstromquelle genutzt werden. Da die Stromregelung relativ schnell ist, kann die Leitung problemlos zum Dimmen per PWM genutzt werden. =Layout= Je kleiner, desto besser - allerdings sollte es auch noch per Hand lötbar sein. Deshalb kommen die im SOT-23-Gehäuse verfügbaren Transistoren BSS138 und BC848 zum Einsatz. Bei den Widerständen reichen welche im 0603-Gehäuse. Um den Platz effektiv nutzen zu können, habe ich zwei Varianten erstellt: eine einseitig und beidseitig bestückbare: <gallery> mleddrv_brd_single.png|Einseitit bestücktes Layout mleddrv_brd_double.png|Zweiseitig bestücktes Layout </gallery> =Leistungsfähigkeit= Widerstände 0603-Gehäuse können in aller Regel 100 mW ab. Das klingt nach nicht sehr viel, reicht aber für die meisten nicht-High-Power-LEDs. Wie oben beschrieben, fallen über den Widerstand ca. 0,65 V ab, mit I = P/U ergibt das einen Strom von 154 mA - da kann man schon fast von "High Power" sprechen. Der begrenzende Faktor liegt aber meist woanders. Der "obere" der Transistoren stellt den Strom ein, über ihn fällt somit Spannungsdifferenz zwischen Eingangsspannung und der Vorwärtsspannung der LED sowie den Spannungsabfall über den Messwiderstand ab. Die Leistung in diesem Transistor berechnet sich zu :<math>P = (U - U_\textrm{f} - U_\textrm{BE}) \cdot I_\textrm{LED}</math> Würde man eine weiße LED (U<sub>LED</sub> = ca. 3,2 V) mit 100 mA und einer Eingangsspannung von 12 V treiben wollen, würde der Transistor stolze 0,8 Watt verbraten. Das wird mit Sicherheit nichts. Im Datenblatt des BSS138 steht eine maximale Leistung von 0,36 Watt und ein Derating von 2,8 mW pro °C. YMMV. Mit diesen Informationen kann man Kennlinienfelder zeichnen - ich hab da schon mal was vorbereitet: <gallery> mleddrv_Kennlinien.png|Kennlinienfeld des LED-Treibers </gallery> Wer das Lesen von Kennlinienfeldern nicht gewohnt ist, hier eine kleine Erläuterung: Zunächst sucht man sich eine Kennlinie aus - für die oben genannte weiße LED wäre das die durchgehend Schwarze. Nun kann man entweder von unten oder links lesen, je nachdem, welchen Wert man sucht. Will man die LED mit 100 mA treiben, sucht man sich auf der Y-Achse die 100 und findet den Schnittpunkt mit der schwarzen Kennlinie. An dieser hangelt man sich nach unten und liest die dazugehörende maximale Betriebsspannung ab: 6,7nochwas Volt. Andersrum: Bei einer Betriebsspannung von 12 V geht man nach oben, wiederum zum Schnittpunkt und dann nach links: irgendwas zwischen 35 und 40 mA. Die Linien im Diagramm sind nicht zufällig gewählt - diese entsprechen in etwa den Vorwärtsspannungen der LEDs in den jeweiligen Farben (schwarz für weiße LEDs, gelbe und orange entsprechen etwa den grünen). Die gestrichelten Linien entsprechen der Reihenschaltung von zwei LEDs der entsprechenden Farbe. Hier sieht man auch, dass durch den höheren Spannungsabfall an den LEDs der Spannungsabfall am Transistor fällt und dadurch höhere Betriebsspannungen möglich werden. Zum Eingangsspannungsbereich kann ich nicht viel sagen, außer dass dieser etwa mindestens so groß wie die LED-Vorwärtsspannung + 0,7 V sein sollte. Das obere Ende wird durch die Transistoren begrenzt. Beim BSS138 wäre das theoretisch die LED-Spannung + 50 Volt. Vorher gibt es aber sicher thermische Probleme. =Download= [[Datei:mleddrv.zip|Schaltplan, Layout, Excel-Datei mit Kennlinienfeld, LtSpice-Daten zum Spielen]] Schaltplan, Layout, Excel-Datei mit Kennlinienfeld, LtSpice-Daten zum Spielen [[Kategorie:Elektronik]] [[Kategorie:Kleine Helferlein]] 65aec204f20c4e150bfee33ccf6331f3148a9bc9 Briefkasteninnenbeleuchtung 0 445 1156 1071 2018-07-15T21:36:05Z Chris 2 Typos korrigiert wikitext text/x-wiki Zugegeben, es hört sich nicht nur bescheuert an, es ist auch so. Trotzdem hatte ich das Bedürfnis, eine Briefkasteninnenbeleuchtung zu bauen. Warum? Nein, nicht (nur) weil ich es kann, sondern weil sie durchaus praktisch ist = Problemstellung = Die Briefkästen des Mietshauses hier sind freistehend und in der dunklen Jahreszeit sieht man aufgrund der etwas ungünstig installierten Außenbeleuchtung durch den Einwurf nicht, ob Post gekommen ist. Durch das Öffnen der Frontklappe sieht und bekommt man zwar den Inhalt, aber dazu bin ich bei der geringen Anzahl von eintrudelnden Briefen schlicht zu faul. Umbauten müssen rückstandsfrei zu entfernen sein, schließlich will ichs nicht mit meinen Vermietern verscherzen. = Idee = In den Briefkasten soll mindestens eine LED, die durch das Öffnen des Deckels aktiviert wird. Die Befestigung findet über Magnete statt, die Stromversorgung durch Batterien. Damit diese nicht unnötig leergesaugt werden, soll die Beleuchtung zeitlich begrenzt sein. = Umsetzung = Zumindest bei der LED ist die Sache schnell klar: weiße PLCC2 liegen hier mehr als genug herum. Um sie sinnvoll zu betreiben, kommen 3 Mignon-Batterien in Serie zum Einsatz. Bei 3,3 Volt (also wenn die Zellen schon halb-platt sind) sind 7 mA mehr als genug, der passende Widerstand hierfür wäre 171 Ohm. Wäre, weil ein einfacher Vorwiderstand an dieser Stelle dumm ist - die Batteriespannung wird mit dem Ladestand fallen - und damit der Strom durch die LED. == LED-Treiber == Besser ist es deshalb, eine Konstantstromquelle zu verwenden. Die lässt sich sehr einfach aufbauen, zwei Transistoren und zwei Widerstände reichen. Der Strom wird über den unteren Widerstand und Transistor definiert: letzterer wird leitend, wenn seine Basis-Emitter-Spannung über ca. 0,7 Volt steigt - diese Spannung muss beim gewünschten Strom eingeprägt werden. Für den Widerstand gilt also: :<math>\textrm{R}=\frac{0.7}{\textrm{I}_\textrm{out}}</math> Der obere Transistor steuert den Strom durch die LED. Der Widerstand dient lediglich als Pull-up und ist daher eher unkritisch. Wer ihn hinreichend groß Dimensionierung will, muss sich den LED-Strom und den Verstärkungsfaktor ansehen. Die mechanische Integration ist einfach: ich habe noch kleine Leiterkärtchen, eigentlich für einen anderen Zweck, aber es passt alles für diese Schaltung drauf. Schrumpfschlauch drüber, kleine Magnete ran, nochmal Schrumpfschlauch. <gallery> Datei:Einfacher_LED-Treiber.png|Schaltplan des einfachen LED-Treibers Datei:Briefkasten_led.jpg|Aufgebauter LED-Triber mit LED, Magnet und Schrumpfschlauch </gallery> Bilder der Innereien gibt es leider keine. == Schalter == Für die Erkennung ob der Deckel offen ist gibt es viele Möglichkeiten: mechanischer Taster, Näherungssensoren, Neigungsschalter, Hallswitches, etc.. Mechanische Schalter brauchen in aller Regel viel Kraft (und viel Gegenkraft, die kann ich bei der Montage nicht bieten) und sind oft empfindlich gegen Feuchtigkeit. Viele Näherungssensoren (optisch, kapazitiv und induktiv) sind aktiv und haben einen relativ großen Eigenverbrauch. Nichts für langen Batteriebetrieb. Neigungsschalter geht, war aber früher dank Quecksilber eine ziemliche Sauerei; die aktuellen sind wahrscheinlich besser aber ich habe aufgrund des Temperaturbereichs Vorbehalte. Schlussendlich habe ich einen Reed-Kontakt verwendet. Hermetisch abgeschlossen, kraftfrei und kein Ruhestrom. Wenn man mechanisch faul ist oder nicht genug Grips in der Birne hat, braucht man einen Öffner - genau das (bzw. einen Wechsler) habe ich bestellt. Um die Integration vorweg zu nehmen: der Kontakt ist auf einer kleinen länglichen Leiterkarte gelandet - lang genug, um einen Magnet zur Montage am Briefkasten verwenden zu können. Jetzt kommt auch die Sache mit dem Grips: Der "Montagemagnet" war stark genug, damit das durch das Metall des Briefkastens verlaufende Feld den Kontakt öffnete. Mit geschickter Positionierung beider Magnete (der zur Montage und dem im Deckel) hätte ich die Felder so ausrichten können, dass sie sich im Deckel-zu-Fall neutralisiert hätten. Hätte-hätte... Aber auch so funktioniert es. Um vor Feuchtigkeit besser geschützt zu sein, kommt alles in Schrumpfschlauch und wird natürlich auf der etwas besser geschützten Seite des Briefkastens installiert. <gallery> Datei:Briefkasten_sensor.jpg|unten: Reedschalter auf Leiterkarte mit Magnet, oben (überbelichtet): Magnet </gallery> == Abschaltautomatik == {{Infobox AVR | Typ = ATtiny13 | Takt = 0,6 | FuseH = FF | FuseL = 61 }} Eigentlich wäre diese prädestiniert für eine Analogschaltung oder einen NE555. Schlussendlich wurde es aber ein ATtiny13. Der ist mit der Aufgabe zwar gänzlich unterfordert, braucht dafür im Schlaf nahezu keinen Strom und zudem fast keine Außenbeschaltung Das Programm könnte sehr einfach sein: Port initialisieren, Pin an, warten, Pin aus. Mit 4,8 MHz Takt braucht der Controller einige Milliampere, was in beiderlei Hinsicht unnötig viel ist. Über die CLKDIV-Fuse kann der Takt auf ein Achtel reduziert werden - besser aber trotzdem nicht überragend. Was ich beim Programmieren übersehen habe: den Watchdog als Taktquelle - 128 kHz und noch etwas stromsparender. Im [http://www.atmel.com/images/doc2535.pdf Datenblatt] kann man sich dazu Figure 19-1 und 19-5 anschauen. Demnach braucht der Chip bei 600 kHz (bei externer Taktquelle) zwischen 0,3 und 0,5 mA - mit dem Watchdog wären es lediglich 0,06 bis 0,09 mA. Statt warten per Delay kann man auch den internen Timer verwenden und die CPU bei Overflow wecken. Nur leider kann man mit weiterlaufendem Takt den Tiny nicht tief genug schlafen schicken, damit es richtig gut wird. Geht man in den Tiefschlaf, bleibt der Takt komplett weg und das war dann für den Timer. Glücklicherweise kann man den Watchdog so konfigurieren, dass er keinen Reset sondern einen Interrupt auslöst. Da er einen eigenen Oszillator hat, ist er zudem unabhängig vom Systemtakt. Sein Vorteiler lässt sich bis in den angenehmen Sekundenbereich einstellen. Im Power-Down und aktivem Watchdog braucht der Prozessor (Figure 19-14) zwischen 4,5 und 7,0 µA. Nachdem das Programm durch ist und sich der Bursche schlafen legt, sinkt der Stromverbrauch (Figure 19-13) auf sehr niedrige 0,2 bis 1,2 µA. Wo liegt nochmal die Selbstentladung von Alkali-Zellen? == Batteriewächter == Darf's ein bisschen mehr sein? Der ATtiny13 hat einen ADC, warum also nicht noch zusätzlich eine Warnung für bald leere Batterien einbauen? Einige AVRs können den ADC verkehrte Welt spielen lassen: Man kann die interne Referenz als Eingang wählen und die Versorgungsspannung als Referenz. Dadurch wird das Ergebnis zwar reziprok aber die Messung braucht keine externe Beschaltung und ist zudem sehr stromsparend. Geht hier leider nicht (Figure 14-1). Es muss also ein externer Spannungsteiler her. Der braucht permanent einen gewissen Strom und das ist Mist. Man kann die Widerstände zwar nach oben dimensionieren, dann wird die Messung durch ADC-bedingte Verfälschungen ungenauer. Ich bin einen etwas faulen (im Sinne von: warum mehr Zeit verschwenden) Kompromiss eingegangen: Der Spannungsteiler wird vom Schaltsignal für die LEDs versorgt. Dadurch haut der Strom nur für die maximal 30 Sekunden ab und zugleich hat der FET einen Pull-down am Gate, falls der IO doch mal floatet. Der Pad-Treiber im AVR dürfte einen leichten Spannungsabfall haben, aber zum einen kann man kalibrieren und zum anderen wird keine besonders hohe Genauigkeit benötigt. Bei der Dimensionierung muss man - wie bereits erwähnt - darauf achten, dass die Messung halbwegs sauber funktioniert aber gleichzeitig nicht unnötig viel Strom verbraucht wird. Natürlich muss auch der Teiler passen. Für diesen Zweck verwende ich gerne [https://www.muellerzumhagen.de/widerstand-ist-zwecklos-pointless-resistance/ Widerstand ist zwecklos], das die Paarung 33 kOhm (top) und 10 kOhm (bottom) ausspuckte. Damit ergibt sich eine maximal messbare Spannung von 4,73 V und ein Stromverbrauch von nicht ganz 105 µA bei 4,5 V. Die Auflösung wäre damit nicht ganz 4,6 mV - deutlich mehr als genug. Der ADC-Wert berechnet sich theoretisch wie folgt: :<math>\textrm{ADC}= \textrm{U}_{\textrm{bat}} \cdot \frac{10\textrm{ k}\Omega}{10\textrm{ k}\Omega+33\textrm{ k}\Omega} \cdot \frac{1024}{1.1\textrm{ V}}</math> Die Messung selbst ist geradeaus: Auswählen der Referenz und Eingang (PB4), Takt festlegen, Interrupt an und los geht's. Um etwas sinnvolles zu machen während die Messung durchgeführt wird, legt sich der Kern schlafen und wird wieder geweckt, sobald diese durch ist (sei(); nicht vergessen!). Anschließend wird der ADC-Wert ausgelesen und der Hardware-Block wieder deaktiviert. Um etwas bessere Ergebnisse zu erlangen, wird die Batteriespannung nicht direkt nach dem Start sondern nach einer Sekunde durchgeführt. Dadurch lassen sich zwei Dinge verknüpfen: Die Batterien sehen eine Last und man ist am richtigen Zeitpunkt, um die LEDs kurz auszuschalten - sollte die Batterieapannung das gesetzte Limit unterschritten haben. <gallery> Datei:Briefkasten_sch1.png|Schaltung </gallery> === Kalibrierung === Aufgrund der Beschaltung sah ich mich genötigt, den ADC zu testen. Der einfachste Weg dafür wäre UART, den es aber nicht gibt. Zumindest nicht in Hardware. Das Format ist relativ einfach, siehe [[wpde:Universal_Asynchronous_Receiver_Transmitter|Wikipedia]]. Idle high, Startbit, Daten und ein bisschen Pause fürs Stopbit (die ich mir gespart hab). Mit dem Wissen, wie lange ein NOP in der CPU dauert die Timings angepasst und los geht's. Mit "normalen" USB<>UART-Adaptern hat man allerdings wenig Spaß: meine Implementierung verwendet - der Faulheit wegen - 10 Datenbits und eine ziemlich krumme Baudrate, die halt einfach gerade gepasst hat. Der Logic Analyzer kann das, die meisten Wandler aber nicht. Aber wer will schon Interoperabilität? Das Ende vom Lied: die Berechnung von oben ist hinreichend genau. == Einbau == Dank der Magnete (Sensor + LEDs) und der Gravitation (Akkus und Mikrocontroller) lässt sich alles befestigen, wo es hin soll. Die Feinausrichtung des Reed-Kontakts geht schnell und einfach. = Es geht besser = Kein Projekt würde mal zweimal genau gleich machen. So auch hier. * LED-Treiber mit FET statt Bipolar-Transistoren aufbauen und dann auch gleich den gemeinsamen FET zum Schalten der Treiber sparen, indem die Versorgung von den Transistoren direkt vom Mikrocontroller kommt. * Spannungsteiler eine Nummer größer dimensionieren und etwas mehr Ungenauigkeit (who cares?!) in Kauf nehmen. Genauso würde ich im AVR gleich den Watchdog als Taktquelle nehmen. * Als Reed-Kontakt einen Schließer nehmen, ihn durch den Befestigungsmagnet "vorspannen" und das Feld durch den Magnet im Deckel neutralisieren. Geht sicher auch auf länger gut und senkt die Bauteilkosten. * Verringern der Betriebsdauer auf 10 Sekunden. Wer starrt schon 30 Sekunden in einen Briefkastenschlitz? <gallery> Datei:Briefkasten_sch2.png|Der etwas verbesserte Schaltplan </gallery> = Unterm Strich = Es ist wirklich sehr praktisch! Die Bilder unten wurden mit gleicher Belichtungseinstellung (mit eingeschalteter Außenbeleuchtung) aufgenommen und spiegeln in etwa die menschliche Helligkeitswahrnehmung wider: <gallery> Datei:Briefkasten_geschlossen.jpg|Geschlossen Datei:Briefkasten_offen.jpg|Geöffnet Datei:Briefkasten_oben.jpg|Blick von oben (keine Post) </gallery> = Trivia = * Der Freund meiner Nachbarin hält mich jetzt wohl für wahnsinnig, weil ich minutenlang vor dem Briefkasten stand und ihn öffnete und schloss ohne ihn zu bemerken. Warum schleicht er auch so herum? * Durch die Mechanische Verkopplung kann man das Klicken des Reedkontakts tatsächlich hören. = Download = [[Datei:Briefkasten.zip|Schaltplan & Firmware]] [[Kategorie:AVR]] 782e8177c05af3067bf94d3a71dad5a47584ff17 Datei:Pirozeda.zip 6 486 1157 1130 2018-08-05T20:28:53Z Chris 2 Chris lud eine neue Version von [[Datei:Pirozeda.zip]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f 1163 1157 2018-08-05T20:47:25Z Chris 2 Chris lud eine neue Version von [[Datei:Pirozeda.zip]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f 1193 1163 2018-08-27T19:32:13Z Chris 2 Chris lud eine neue Version von [[Datei:Pirozeda.zip]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda 3dplot.png 6 495 1158 2018-08-05T20:38:34Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Eagle bom.png 6 496 1164 2018-08-19T20:57:08Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Eagle bom mw.zip 6 497 1165 2018-08-19T20:58:40Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f EAGLE-BOM 0 498 1166 2018-08-19T20:59:18Z Chris 2 Die Seite wurde neu angelegt: „Ein von Bastlern viel zu selten benutztes Feature in vermutlich egal welcher EDA-Software ist die BOM. Da ich in der Hinsicht über die Zeit besser geworden b…“ wikitext text/x-wiki Ein von Bastlern viel zu selten benutztes Feature in vermutlich egal welcher EDA-Software ist die BOM. Da ich in der Hinsicht über die Zeit besser geworden bin und diese in den meisten meiner EAGLE-Projekte pflege, kommt sie in aller Regel auch auf die entsprechende Artikel-Seite hier im Wiki. Bis jetzt war es allerdings so, dass ich sie nach Excel exportiert habe und die Formatierung für MediaWiki manuell vorgenommen habe. Warum nicht einfach das ULP anpassen, damit es direkt Tabellen für MediaWiki ausspucken kann? Gesagt, getan: <gallery> eagle_bom.png|Screenshot des angepassten BOM-ULP </gallery> =Download= [[Datei:eagle_bom_mw.zip]] [[Kategorie:Sonstiges, Software, kleine Helferlein, EAGLE]] 0714c674861e15aa6a05f10ba2d2597ec5c60f2c 1167 1166 2018-08-19T21:00:16Z Chris 2 wikitext text/x-wiki Ein von Bastlern viel zu selten benutztes Feature in vermutlich egal welcher EDA-Software ist die BOM. Da ich in der Hinsicht über die Zeit besser geworden bin und diese in den meisten meiner EAGLE-Projekte pflege, kommt sie in aller Regel auch auf die entsprechende Artikel-Seite hier im Wiki. Bis jetzt war es allerdings so, dass ich sie nach Excel exportiert habe und die Formatierung für MediaWiki manuell vorgenommen habe. Warum nicht einfach das ULP anpassen, damit es direkt Tabellen für MediaWiki ausspucken kann? Gesagt, getan: <gallery> eagle_bom.png|Screenshot des angepassten BOM-ULP </gallery> =Download= [[Datei:eagle_bom_mw.zip]] [[Kategorie:Sonstiges]] [[Kategorie:Software]] [[Kategorie:kleine Helferlein]] [[Kategorie:EAGLE]] ccaad7cd6019d2e84751c4d2e161d0de4fe69522 1169 1167 2018-08-19T21:03:43Z Chris 2 wikitext text/x-wiki Ein von Bastlern viel zu selten benutztes Feature in vermutlich egal welcher EDA-Software ist die BOM. Da ich in der Hinsicht über die Zeit besser geworden bin und diese in den meisten meiner EAGLE-Projekte pflege, kommt sie in aller Regel auch auf die entsprechende Artikel-Seite hier im Wiki. Bis jetzt war es allerdings so, dass ich sie nach Excel exportiert habe und die Formatierung für MediaWiki manuell vorgenommen habe. Warum nicht einfach das ULP anpassen, damit es direkt Tabellen für MediaWiki ausspucken kann? Gesagt, getan: <gallery> eagle_bom.png|Screenshot des angepassten BOM-ULP </gallery> Als Basis diente die in EAGLE 7.3.0 mitgelieferte ULP. =Installation= Den Inhalt der ZIP-Datei einfach in den ULP-Ordner von EAGLE kopieren, dann mit "run bom" ausführen oder übers Menü Datei -> Exportieren -> BOM. =Download= [[Datei:eagle_bom_mw.zip]] [[Kategorie:Sonstiges]] [[Kategorie:Software]] [[Kategorie:Kleine Helferlein]] [[Kategorie:EAGLE]] c4fa4fc1237dd94e6f4991f7c219d236ae299516 Datei:Mcp2210 usb-spi assy bot.png 6 499 1171 2018-08-23T20:56:02Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2210 usb-spi assy top.png 6 500 1172 2018-08-23T20:56:03Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2210 usb-spi brd bot.png 6 501 1173 2018-08-23T20:56:04Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2210 usb-spi brd top.png 6 502 1174 2018-08-23T20:56:05Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2210 usb-spi cc1101 photo.jpg 6 503 1175 2018-08-23T20:56:06Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2210 usb-spi nrf24l01 photo.jpg 6 504 1176 2018-08-23T20:56:08Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2210 usb-spi photo.jpg 6 505 1177 2018-08-23T20:56:10Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2210 usb-spi sch.png 6 506 1178 2018-08-23T20:56:10Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2221 usb-i2c assy bot.png 6 507 1179 2018-08-23T20:56:11Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2221 usb-i2c assy top.png 6 508 1180 2018-08-23T20:56:12Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2221 usb-i2c brd bot.png 6 509 1181 2018-08-23T20:56:13Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2221 usb-i2c brd top.png 6 510 1182 2018-08-23T20:56:13Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2221 usb-i2c photo.jpg 6 511 1183 2018-08-23T20:56:15Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2221 usb-i2c sch.png 6 512 1184 2018-08-23T20:56:16Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:MCP-USB-Bridge.zip 6 513 1185 2018-08-23T20:56:17Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f MCP-USB-Bridge 0 514 1186 2018-08-23T20:57:22Z Chris 2 Seite erstellt wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den MCP2221 (I²C) und MCP2210 (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas), für Python gibt es [https://github.com/nonNoise/PyMCP2221A eine Lib] mit Unterstützung der Basisfunktionen. =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz Designdaten =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 4cd1c02775a0ae5aef96dbb78bfd890a9a3701c0 1187 1186 2018-08-23T20:58:05Z Chris 2 /* Download */ Datei-NS vergessen wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den MCP2221 (I²C) und MCP2210 (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas), für Python gibt es [https://github.com/nonNoise/PyMCP2221A eine Lib] mit Unterstützung der Basisfunktionen. =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz Designdaten =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 8f7b67adbbf6b646525e3164acecda5a5858b11b 1188 1187 2018-08-23T20:58:46Z Chris 2 /* USB-I²C-Bridge */ Link korrigiert wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den MCP2221 (I²C) und MCP2210 (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas), für Python gibt es [https://github.com/nonNoise/PyMCP2221A eine Lib] mit Unterstützung der Basisfunktionen. =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz Designdaten =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 378850da4790d58ce18797b3c422c06a5fa27f3b 1190 1188 2018-08-23T21:01:49Z Chris 2 wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den MCP2221 (I²C) und MCP2210 (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas), für Python gibt es [https://github.com/nonNoise/PyMCP2221A eine Lib] mit Unterstützung der Basisfunktionen. =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz Designdaten =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 1b68c724ed7a5f534da294cdfbdd7834a099ea6e 1191 1190 2018-08-23T21:04:02Z Chris 2 Links hinzugefügt wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas), für Python gibt es [https://github.com/nonNoise/PyMCP2221A eine Lib] mit Unterstützung der Basisfunktionen. =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz Designdaten =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 905b85930bb2c080632276671fd9eac511499ad7 Kühlung für Zhongdi ZD-939L 0 367 1192 1001 2018-08-23T21:07:58Z Chris 2 /* Nachtrag 19.04.2015 */ Formatierung korrigiert wikitext text/x-wiki Vor geraumer Zeit hab ich mir eine Zhondi ZD-939L auf den Basteltisch gestellt. Diese Heißluftlötstation ist gerade beim Entlöten von SMD-Bauteilen ein sehr nützlicher Helfer. [[Datei:ZD-939L Hinweis.JPG|thumb|Aufkleber als Workaround]] Eines hat mich allerdings vom ersten Tag weg gestört: sie hat keinen Nachlauf zum Kühlen des Heizelements. Als "Workaround" hat der Importeur lediglich einen Hinweis angebracht, dass man vor dem Abschalten auf die Mindesttemperatur herunterdrehen und eine Minute warten solle. Mit dem Warten kann ich leben, allerdings ist das Einstellen der Temperatur etwas nervig: Minus-Taster drücken und halten und sich für jedes Grad einen Pieps anhören. Nur um beim Nächsten Einschalten genau das Gegenteil zu machen. selbstverständlich ebenfalls mit akustischer Untermalung. Dabei gibt es die Heißluft-Station (neben der Version mit Nachlauf) auch mit dienen Schalter fürs Heizelement. Warum hat das meine nicht? Es wird höchste Zeit, dass sich das ändert. =Analyse= [[Datei:ZD-939L_Innenleben.jpg|thumb|Blick auf die hintere Leiterkarte]] Auf das Ding und reingeschaut. Die Elektronik ist auf 3 Leiterkarten verteilt - hinten befindet sich ein teilbestücktes Board auf das die Netzleitung führt. Nachdem sich nichts darauf befindet, das auf Regelung hindeutet, dürfte es der Leistungsteil sein. Vorne im Gehäuse findet sich neben der Leiterkarte mit den Tastern vom Frontpanel auch die Platine mit dem Display. Die 3 schwarzen Vielbeiner darauf lassen erahnen: hier wird höchstwahrscheinlich geregelt. Heizung abdrehen könnte man nun sowohl auf der Leistungs- als auch der mutmaßlichen Reglerplatine. Man könnte natürlich auch direkt in die Leitung zum Heizelement eingreifen - aber warum sich die Finger an 230 V verbrennen, wenn man es auch einfacher und sicher haben kann? Ein genauerer Blick auf die Display-Platine kann also nicht schaden: <gallery> Datei:ZD-939L Regler.JPG|Die Reglerplatine </gallery> Der 8-beinige Chip links ist ein LM358, also ein Operationsverstärker. Beim mittleren Chip im TQFP-Gehäuse handelt es sich um einen Silabs C8051F310 - einem Mikrocontroller. Rechts im Bild befindet sich ein Holtek HT1621B. Holtek kennt man auch als Mikrocontroller-Hersteller - aber zwei Mikrocontroller für einen einfachen Regler? Nicht ganz. Der Holtek ist lediglich ein LCD-Controller, was auch die Leiterbahnen zu ihm erklärt. Die Regelung übernimmt alleinig der Silabs-Chip. Interessanter als die Regelung und das Display ist für den Umbau, über welche Anschlüsse die Heizung angesteuert wird. Drei der vier Stiftleisten sind mit der Platine hinten verbunden. Die 4-polige Stiftleiste links im Bild führt zur Taster-Platine und fällt damit schon mal weg. Die untere zweipolige Stifleiste ist ein Kandidat - nachdem sie aber verdächtig nahe am LM358, ein paar diskreten Bauteilen und einem Poti liegt, dürfte es sich um den Anschluss für den Temperaturfühler sein. Alle Leitungen außer dieser verbunden bestätigt den Verdacht: Keine Temperaturanzeige. Bleiben nur noch zwei. Die links obere sieht verdächtig nach Stromversorgung aus: etwas dickere Leiterbahnen, Dioden und Kondensatoren. Nicht zuletzt ein 78L05. Warum aber 3 Pins? Eingangsspannung, Masse und Ausgangsspannung? Nein, vermutlich handelt es sich um eine symmetrische Versorgung - entweder fürs Display oder den Operationsverstärker. Ein Blick in den hinteren Teil der Lötstation bestätigt es: Ein Trafo mit Mittelabzapfung. Die Heizung muss also von der Stiftleiste rechts oben angesteuert werden. Am Stecker hängen zwei Drähte, was die Sache leichter macht. Masse lässt sich durchpiepsen und damit ist auch der Ausgang gefunden. Muss nur noch geklärt werden, wann welche Spannung anliegt und ob man einfach so einen Schalter einbringen kann. Multimeter angehängt und den Aparillo losbrummen lassen: 5V, wenn die Heizung an ist. Um sicherzustellen, dass die 5V berührungssicher sind, schnell gegen das Gehäuse, das mit PE verbunden ist: 0V, also galvanisch getrennt. Ausgezeichnet! =Umbau= Ein Ort für den zusätzlichen Schalter ist schnell gefunden: Neben dem Hauptschalter ist noch Platz. Der Akkuschrauber leiert ein Loch in die Platte und der Schalter ist drin. Für die elektrische Verbindung habe ich die Leitung zum "Backpanel" aufgetrennt und den Schalter einfach eingefügt. Da ich die Schaltung dahinter nicht genauer ansehen wollte, habe ich mich für die sicherere Ansteuerung entschlossen - theoretisch könnte man einfach eine der Leitungen auftrennen und den Schalter einfügen. Allerdings bekommt dann die Schaltung "hinten" entweder das Signal vom Mikrocontroller oder floatet durch die Gegend. Da das nicht besonders toll ist, wechselt der Schalter zwischen dem ursprünglichen Pfad und Masse. So gibt es immer einen definierten Pegel und Probleme werden bestmöglich ausgeschlossen. <gallery> Datei:ZD-939L Elektronik vorne.JPG|Umgebaute Elektronik </gallery> Der erste Test im noch auseinander gebauten Zustand spricht für Erfolg: die Soll-Temperatur ist bei 160 °C, die Ist-Temperatur bleibt bei 25 °C. Nach Kippen des Schalters klettert die Anzeige wie vorher nach oben. <gallery> Datei:ZD-939L Front umgebaut.JPG|Funktionstest mit ausgeschalteter Heizung </gallery> =J-EXT= Auf dem Board befinden sich noch zwei Vorhalte für Stiftleisten. Eine unbeschriftete (vermutlich zum Download der Firmware) und eine namens J-EXT. Rein aus Neugierde habe ich mir letztere etwas genauer angesehen, vielleicht spricht das Board ja mit einem. Die Leiterbahnen führen schon einmal alle zum Mikrocontroller, zusammen mit dessen Datenblatt lassen sich die Pins zuordnen. P3.x haben leider keine spezielle Peripherie zugeordnet, also eher unwahrscheinlich, dass da UART rauskommt. Möglich ist aber alles. Also Spannung mit dem Scope nachgemessen und nach positivem Befund den Logic-Analyzer angeschlossen: [[Datei:ZD-939L_Logic-Analyzer.png]] Aus den Daten lässt sich folgende Zuordnung ableiten: {| class="wikitable" |- ! Pin J-EXT !! Pin µC !! Pin-Name !! Funktion |- | 1 || - || - || +5V |- | 2 || 7 || P3.1 || ? |- | 3 || 9 || P3.3 || Clock |- | 4 || 10 || P3.4 || Data |- | 5 || - || - || GND |} Ein "Datenpaket" dauert etwa 2,6 ms und wird alle 20 ms gesendet. Allem Anschein nach werden die Daten in 16-Bit-Gruppen geschickt, zumindest bleibt der Clock nach 16 Bits immer ein bisschen länger High. Die Daten habe ich nicht genauer untersucht, da für mich der Reiz einfach nicht da ist. Wer es versuchen will, kann sein Glück mit meiner Aufzeichnung versuchen: [[Datei:ZD-939L J-EXT.zip]] Die Daten wurden mit Saleae Logic 1.1.18 Beta erstellt. Wenn ich mich richtig erinnere, war die Temperatur auf 160 °C Soll eingestellt und eine Ist-Temperatur von 25 °C (weniger macht das Teil anscheinend nicht) angezeigt. =Nachtrag 19.04.2015= Manfred hat sich etwas mehr Arbeit gemacht und und der Station zusätzlich noch eine Status-LED und eine niedrigere Stufe für den Luftdurchsatz hinzugefügt. Hier seine Beschreibung - vielen Dank dafür! <code> Jetzt habe ich endlich mal meine Heißluftstation bearbeitet. Etwas ange****t bin ich ja, dass da tatsächlich direkt mit Netzspannung geheizt wird, hätte ich nicht erwartet. Eigentlich kann da ein passender Schalter rein und fertig - aber, um das ordentlich zu machen, müsste ich die Kiste zerlegen, wegen Feilspänen, da habe ich keine Lust zu. Ich habe Deinen Vorschlag gegriffen und trenne die Steuerleitung. Gegen die Langeweile noch eine LED rein, weiße sieht man unter 1 mA schon leuchten. Im Gegensatz zur Beschreibung stehen da keine 5 V an der Steuerleitung, ich messe knapp 3,2 Volt. Wenn die leuchtet, ist also Abkühlphase! Die Luftmenge ist mir zu hoch, auah, am Drehpoti liegt Netzspannung. Das Ding hat 470 kOhm, mal einen R in Reihe probieren, bis gut 650 k liefert meine Pumpe noch Luft. Da ist jetzt ein weiterer Schalter drin, der 220 k in Reihe legt - eigentlich wäre auch ein 1 Meg-Poti mit parallel 2 MOhm klug, wenn es denn im Vorrat gewesen wäre. Vielleicht sollte dieser Punkt im Wiki ergänzt werden? Ich habe Kippschalter MTA-106 von Knitter eingesetzt, die können 250 Volt, haben aber keine VDE-Zertifizierung - von daher bin ich an der Stelle nicht ganz sauber. [...] Wie man sieht, sieht man an den Kippschaltern keine Mutter, Bastelei darf gerne auch anständig aussehen. Die Schalter haben Feingewinde, der Stahl vom Chinesengehäuse ist gut, also habe ich Gewinde geschnitten und von hinten gekontert. </code> <gallery> Datei:ZD-939L M Stromlauf_grau_1200.png|Stromlaufplan der Änderung Datei:ZD-939L M Detail_Schalter_1600_60.jpg|Änderungen von innen Datei:ZD-939L M Schalterfeld_1200_60.jpg|...und von vorne </gallery> = Nachtrag 26.05.2015 = Mittlerweile gibt es beim Ramschmax auch eine Version mit [http://www.pollin.de/shop/dt/MjM4OTUxOTk-/Werkstatt/Loettechnik/Loetgeraete/Heissluft_Loetstation_mit_LCD_ZD_939L_4_Wechselduesen.html fertig eingebautem Kühlschalter]. =Siehe auch= * [http://hobbyelektronik.org/b/2014/05/eine-kleine-anmerkung-zu-chinesischen-namen/ Eine kleine Anmerkung zu chinesischen Namen] [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] 27cbb314d59cd95c2060c3e83da8e4d7f3178079 Datei:Pirozeda.zip 6 486 1196 1193 2018-08-27T20:49:35Z Chris 2 Chris lud eine neue Version von [[Datei:Pirozeda.zip]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Hobbyelektronik.org:Impressum 4 4 1197 1153 2018-10-01T17:59:56Z Chris 2 Abschnitt "Nutzung von Inhalten" hinzugefügt wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS1.2 ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) a2d2bbf8c87c9703d809d2d0c05aaac16ed51d12 MCP-USB-Bridge 0 514 1198 1191 2018-10-27T11:41:45Z Chris 2 /* Anmerkungen */ wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas), für Python gibt es [https://github.com/nonNoise/PyMCP2221A eine Lib] mit Unterstützung der Basisfunktionen. =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. Deshalb: es wird eine Version 2 geben. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] da78c08a9acc468549ab3354828d84550a9263e7 1202 1198 2018-10-27T14:11:49Z Chris 2 Python-Lib hinzugefügt wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. Deshalb: es wird eine Version 2 geben. =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaub, habe ich angenfangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 | 547 | 39,5 | 78,84 | 639 | 33,81 | 67,5 |- | 100,4 | 313 | 69,03 | 68,75 | 479 | 45,11 | 44,9 |- | 150,9 | 235 | 91,95 | 60,92 | 320 | 67,52 | 44,7 |- | 201,7 | 235 | 91,95 | 45,59 | 320 | 67,52 | 33,5 |- | 252,6 | 157 | 137,63 | 54,48 | 240 | 90,03 | 35,6 |- | 303,8 | 158 | 136,76 | 45,02 | 240 | 90,03 | 29,6 |- | 347,8 | 158 | 136,76 | 39,32 | 240 | 90,03 | 25,9 |- | 406,8 | 158 | 136,76 | 33,62 | 240 | 90,03 | 22,1 |- | 452,8 | 158 | 136,76 | 30,2 | 240 | 90,03 | 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:mcp22xx_py.zip]] Python-Lib v0.1, aktuell nur für MCP2221, mit Beispielen [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 23a42d46fee73bd6912a69b5edfaf6303ef3a9fc 1203 1202 2018-10-27T14:13:18Z Chris 2 wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. Deshalb: es wird eine Version 2 geben. =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaub, habe ich angenfangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:mcp22xx_py.zip]] Python-Lib v0.1, aktuell nur für MCP2221, mit Beispielen [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] d54ea1f11d92807916b076a43663d52e4cb86a11 1206 1203 2018-10-27T14:16:33Z Chris 2 wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. Deshalb: es wird eine Version 2 geben. =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:mcp22xx_py.zip]] Python-Lib v0.1, aktuell nur für MCP2221, mit Beispielen [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] ad5bf265adb29977802e73e0245467a82041732d 1209 1206 2018-11-04T16:43:12Z Chris 2 Zugehörige Blogposts verlinkt, Text bei Download(s) korrigiert wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. Deshalb: es wird eine Version 2 geben. =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= [[Datei:mcp22xx_py.zip]] Python-Lib v0.1, aktuell nur für MCP2221, mit Beispielen [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] dead590e25fe4b2b5f57914399ec35b0026ed851 Datei:Mcp22xx py.zip 6 515 1199 2018-10-27T14:10:43Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2211 usb-i2c efficiency.png 6 516 1200 2018-10-27T14:10:44Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Mcp2211 usb-i2c throughput.png 6 517 1201 2018-10-27T14:10:44Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Hauptseite 0 1 1204 1195 2018-10-27T14:15:22Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] ==Änderungen== *27.10.2018 [[MCP-USB-Bridge#Python-Lib]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] 19e343df7d690f00962940259ddf96599c147cf9 1205 1204 2018-10-27T14:15:47Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] ==Änderungen== *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] 4fd3a3d6b35aca41a9e105553f6d145993da92a4 1223 1205 2019-01-03T20:34:38Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. ==[//hobbyelektronik.org/b/ Blog]== <WPPlatest /> ==Neues== *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] ==Änderungen== *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] 37396da55a71bc26f6ab6dd0308c3548cb0dfe75 1224 1223 2019-01-03T20:36:38Z Chris 2 Neues und Änderungen zusammengefasst, ist glaube ich sinnvoller. wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] 493eb26eacb332d7fd2632acd20f177f85b11ff8 1230 1224 2019-01-03T21:32:59Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] a858f98b941a4421a811a2f77b3e7102d899cc31 1237 1230 2019-02-10T21:30:17Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] c28137859c69ccbe83e927d58301be206bcf897c Pirozeda 0 487 1207 1194 2018-11-03T19:04:28Z Chris 2 /* Hardware */ Reichelt-Bestellnummern korrigiert wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] 754878d1afcca8d1de953d5c351ba62999ea367f 1218 1207 2019-01-03T20:24:28Z Chris 2 Pirozeda-HAT hinzugefügt wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Pirozeda-HAT= Wie bereits weiter oben und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADMUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar geschmackssache aber in Hinblick auf Platz das beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. '''ACHTUNG: Die Hardware ist bis jetzt weder aufgebaut noch getestet. Leiterkarten sind auf dem Weg zu mir.''' ==Bestückungsvarianten== Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ===Variante 1: Direkt=== Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist dass neben der gemeinsamen Masse mit der Solaranlage Backfeeding entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Die Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ===Variante 2: Optokoppler=== Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit Optokoppler </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || R13 || 1k || R0603 || RND 0603 1 470 |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ===Variante 3: ADUM-Isolator=== Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || R9, R10 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Bestückungsoptionen== Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_optional_assy.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ===Option: HAT-ID=== Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEPRom ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 6 || C6 || 100n || C0603 || X7R-G0603 100N |} Aktuell gibt es noch keine weitere Unterstützung hierfür. ===Option: Real-Time-Clock=== Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 4 || R5, R6, R7, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 2 || Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. ===Option: I²C(-OLED) + Taster=== Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |} ===Option: Status-LEDs=== Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. ==Firmware== Grundsätzlich läuft die Firmware des original-Adapters auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] 458bc48dd9b77141470f2253df45abd7d819ec0d 1219 1218 2019-01-03T20:26:54Z Chris 2 /* Option: I²C(-OLED) + Taster */ Bild mit Bestückungsoptionen für Stromversorgung I²C hinzugefügt wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Pirozeda-HAT= Wie bereits weiter oben und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADMUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar geschmackssache aber in Hinblick auf Platz das beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. '''ACHTUNG: Die Hardware ist bis jetzt weder aufgebaut noch getestet. Leiterkarten sind auf dem Weg zu mir.''' ==Bestückungsvarianten== Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ===Variante 1: Direkt=== Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist dass neben der gemeinsamen Masse mit der Solaranlage Backfeeding entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Die Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ===Variante 2: Optokoppler=== Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit Optokoppler </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || R13 || 1k || R0603 || RND 0603 1 470 |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ===Variante 3: ADUM-Isolator=== Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || R9, R10 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Bestückungsoptionen== Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_optional_assy.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ===Option: HAT-ID=== Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEPRom ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 6 || C6 || 100n || C0603 || X7R-G0603 100N |} Aktuell gibt es noch keine weitere Unterstützung hierfür. ===Option: Real-Time-Clock=== Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 4 || R5, R6, R7, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 2 || Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. ===Option: I²C(-OLED) + Taster=== Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |} ===Option: Status-LEDs=== Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. ==Firmware== Grundsätzlich läuft die Firmware des original-Adapters auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] 601b1a532964029eaaea26ad9ef138e509ccdca4 1221 1219 2019-01-03T20:28:54Z Chris 2 /* Download */ wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Pirozeda-HAT= Wie bereits weiter oben und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADMUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar geschmackssache aber in Hinblick auf Platz das beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. '''ACHTUNG: Die Hardware ist bis jetzt weder aufgebaut noch getestet. Leiterkarten sind auf dem Weg zu mir.''' ==Bestückungsvarianten== Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ===Variante 1: Direkt=== Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist dass neben der gemeinsamen Masse mit der Solaranlage Backfeeding entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Die Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ===Variante 2: Optokoppler=== Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit Optokoppler </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || R13 || 1k || R0603 || RND 0603 1 470 |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ===Variante 3: ADUM-Isolator=== Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || R9, R10 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Bestückungsoptionen== Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_optional_assy.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ===Option: HAT-ID=== Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEPRom ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 6 || C6 || 100n || C0603 || X7R-G0603 100N |} Aktuell gibt es noch keine weitere Unterstützung hierfür. ===Option: Real-Time-Clock=== Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 4 || R5, R6, R7, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 2 || Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. ===Option: I²C(-OLED) + Taster=== Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |} ===Option: Status-LEDs=== Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. ==Firmware== Grundsätzlich läuft die Firmware des original-Adapters auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format '''Achtung: Bisher nicht verifiziert!''' ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] b6559875f576a5ec34bc37407fd2ef63493a2243 1222 1221 2019-01-03T20:31:32Z Chris 2 /* Bestückungsoptionen */ Dreher im Dateinamen wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =Pirozeda-HAT= Wie bereits weiter oben und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADMUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar geschmackssache aber in Hinblick auf Platz das beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. '''ACHTUNG: Die Hardware ist bis jetzt weder aufgebaut noch getestet. Leiterkarten sind auf dem Weg zu mir.''' ==Bestückungsvarianten== Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ===Variante 1: Direkt=== Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist dass neben der gemeinsamen Masse mit der Solaranlage Backfeeding entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Die Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ===Variante 2: Optokoppler=== Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit Optokoppler </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || R13 || 1k || R0603 || RND 0603 1 470 |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ===Variante 3: ADUM-Isolator=== Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || R9, R10 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Bestückungsoptionen== Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ===Option: HAT-ID=== Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEPRom ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 6 || C6 || 100n || C0603 || X7R-G0603 100N |} Aktuell gibt es noch keine weitere Unterstützung hierfür. ===Option: Real-Time-Clock=== Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 4 || R5, R6, R7, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 2 || Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. ===Option: I²C(-OLED) + Taster=== Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |} ===Option: Status-LEDs=== Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. ==Firmware== Grundsätzlich läuft die Firmware des original-Adapters auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel. =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format '''Achtung: Bisher nicht verifiziert!''' ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] a9869fc6585dc976237a8ce760625ab7800394c8 1242 1222 2019-02-10T21:40:50Z Chris 2 wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format '''Achtung: Bisher nicht verifiziert!''' ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] 3cfee3b4b71213e242b752dd66b2218aca0ca57e 1243 1242 2019-02-10T21:41:11Z Chris 2 Kategorie wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format '''Achtung: Bisher nicht verifiziert!''' ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 8108c71905335b95cd9052b838476f455b1e9c0e Testseite 0 2 1208 1088 2018-11-04T16:18:21Z Chris 2 wikitext text/x-wiki <WPPtags tags="MCP2221" /> {{Infobox AVR | Typ = AtMega Schießmichtot | Takt = 42 | FuseH = 0xFF | FuseL = 0xFF }} :<math>\int_{0}^{42} \frac{23}{42}x^{2} dx</math> <math>\int_{0}^{42} \frac{23}{42}x^{2} dx</math> Testseite, für interne Verwendung. <source lang="php"> <?php ladida(); $var = fopen("foobar"); ?> </source> [[Kategorie:Elektronik]] 45927cd3bb59abf7ead827d52bbbd1a850a85c1e Datei:Pirozeda hat 0.1 adum assy.png 6 518 1210 2019-01-03T20:21:50Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 adum sch.png 6 519 1211 2019-01-03T20:21:51Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 assy optional.png 6 520 1212 2019-01-03T20:21:52Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 direct assy.png 6 521 1213 2019-01-03T20:21:53Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 direct sch.png 6 522 1214 2019-01-03T20:21:54Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 i2c polarity.png 6 523 1215 2019-01-03T20:23:02Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 opto assy.png 6 524 1216 2019-01-03T20:23:04Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 opto sch.png 6 525 1217 2019-01-03T20:23:04Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat.zip 6 526 1220 2019-01-03T20:28:24Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Resol nano 0.1 assy bot.png 6 527 1225 2019-01-03T21:29:33Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Resol nano 0.1 assy top.png 6 528 1226 2019-01-03T21:29:34Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Resol nano 0.1 sch.png 6 529 1227 2019-01-03T21:29:35Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Vbus nano.zip 6 530 1228 2019-01-03T21:29:36Z Chris 2 Datei hochgeladen mit MsUpload wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f VBus-Decoder 0 120 1229 1032 2019-01-03T21:30:35Z Chris 2 VBus-Adapter Nano hinzugefügt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein ich es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Die Schaltung wurde simuliert und in ähnlicher Form bereits aufgebaut. Diese Version ist allerdings noch nicht getestet, Leiterkarten sind auf dem Weg. Wer eine will kann sich gerne bei mir melden. =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei_Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] 2434a062e9a74f2f9d6e20f4ba5cf44d32f71541 1231 1229 2019-01-03T21:34:38Z Chris 2 /* Download */ vertippt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein ich es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Die Schaltung wurde simuliert und in ähnlicher Form bereits aufgebaut. Diese Version ist allerdings noch nicht getestet, Leiterkarten sind auf dem Weg. Wer eine will kann sich gerne bei mir melden. =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] 4e119817bc0d797da83723a18e9908e48b0e79ac 1232 1231 2019-01-03T21:36:33Z Chris 2 /* VBus-Adapter Nano */ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein ich es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite </gallery> Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Die Schaltung wurde simuliert und in ähnlicher Form bereits aufgebaut. Diese Version ist allerdings noch nicht getestet, Leiterkarten sind auf dem Weg. Wer eine will kann sich gerne bei mir melden. =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] 22739bb3091308a1df1f0cce74ff30cc580daa3d EAGLE-BOM 0 498 1233 1169 2019-02-10T21:18:24Z Qsysopr 1 Qsysopr verschob die Seite [[EAGLE-BOM für MediaWiki]] nach [[EAGLE-BOM]]: wird bisschen universeller ;) wikitext text/x-wiki Ein von Bastlern viel zu selten benutztes Feature in vermutlich egal welcher EDA-Software ist die BOM. Da ich in der Hinsicht über die Zeit besser geworden bin und diese in den meisten meiner EAGLE-Projekte pflege, kommt sie in aller Regel auch auf die entsprechende Artikel-Seite hier im Wiki. Bis jetzt war es allerdings so, dass ich sie nach Excel exportiert habe und die Formatierung für MediaWiki manuell vorgenommen habe. Warum nicht einfach das ULP anpassen, damit es direkt Tabellen für MediaWiki ausspucken kann? Gesagt, getan: <gallery> eagle_bom.png|Screenshot des angepassten BOM-ULP </gallery> Als Basis diente die in EAGLE 7.3.0 mitgelieferte ULP. =Installation= Den Inhalt der ZIP-Datei einfach in den ULP-Ordner von EAGLE kopieren, dann mit "run bom" ausführen oder übers Menü Datei -> Exportieren -> BOM. =Download= [[Datei:eagle_bom_mw.zip]] [[Kategorie:Sonstiges]] [[Kategorie:Software]] [[Kategorie:Kleine Helferlein]] [[Kategorie:EAGLE]] c4fa4fc1237dd94e6f4991f7c219d236ae299516 1235 1233 2019-02-10T21:27:17Z Chris 2 wikitext text/x-wiki Ein von Bastlern viel zu selten benutztes Feature in vermutlich egal welcher EDA-Software ist die BOM. Da ich in der Hinsicht über die Zeit besser geworden bin und diese in den meisten meiner EAGLE-Projekte pflege, kommt sie in aller Regel auch auf die entsprechende Artikel-Seite hier im Wiki. Als Basis diente die in EAGLE 7.3.0 mitgelieferte ULP. =Export-Formate= ==MediaWiki-Export== Bis jetzt war es allerdings so, dass ich sie nach Excel exportiert habe und die Formatierung für MediaWiki manuell vorgenommen habe. Warum nicht einfach das ULP anpassen, damit es direkt Tabellen für MediaWiki ausspucken kann? Gesagt, getan: <gallery> eagle_bom.png|Screenshot des angepassten BOM-ULP </gallery> ==JSON-Export== Wer [[wpde:JSON|JSON]] nicht kennt, sollte das schnell ändern. Es handelt sich um ein Dateiformat, das der Javascript-Notation für das Generieren von Objekten entspricht - es ist sehr kompakt und gleichzeitig einfach zu parsen. Warum also nicht für den BOM-Export in EAGLE verwenden? Ein Wort der Warnung sei angebracht: es wird keine Stringify-Funktion verwendet, im Prinzip ist es nur ein umgebauter CSV-Export. Escaping von Sonderzeichen findet aktuell nicht statt. =Installation= Den Inhalt der ZIP-Datei einfach in den ULP-Ordner von EAGLE kopieren, dann mit "run bom" ausführen oder übers Menü Datei -> Exportieren -> BOM. =Download= [[Datei:eagle_bom.zip]] ==Änderungen== ===2018-08-09: Version 1.11=== Support für MediaWiki-Tabellen hinzugefügt ===2019-02-10: Version 1.12=== Support für JSON hinzugefügt [[Kategorie:Sonstiges]] [[Kategorie:Software]] [[Kategorie:Kleine Helferlein]] [[Kategorie:EAGLE]] 6d2f08e55769103c53c9a48a7c1adc906b37e6dd 1238 1235 2019-02-10T21:30:54Z Chris 2 wikitext text/x-wiki Ein von Bastlern viel zu selten benutztes Feature in vermutlich egal welcher EDA-Software ist die BOM. Da ich in der Hinsicht über die Zeit besser geworden bin und diese in den meisten meiner EAGLE-Projekte pflege, kommt sie in aller Regel auch auf die entsprechende Artikel-Seite hier im Wiki. Als Basis diente die in EAGLE 7.3.0 mitgelieferte ULP. =Export-Formate= ==MediaWiki-Tabelle== Bis jetzt war es allerdings so, dass ich sie nach Excel exportiert habe und die Formatierung für MediaWiki manuell vorgenommen habe. Warum nicht einfach das ULP anpassen, damit es direkt Tabellen für MediaWiki ausspucken kann? Gesagt, getan: <gallery> eagle_bom.png|Screenshot des angepassten BOM-ULP </gallery> ==JSON== Wer [[wpde:JSON|JSON]] nicht kennt, sollte das schnell ändern. Es handelt sich um ein Dateiformat, das der Javascript-Notation für das Generieren von Objekten entspricht - es ist sehr kompakt und gleichzeitig einfach zu parsen. Warum also nicht für den BOM-Export in EAGLE verwenden? Ein Wort der Warnung sei angebracht: es wird keine Stringify-Funktion verwendet, im Prinzip ist es nur ein umgebauter CSV-Export. Escaping von Sonderzeichen findet aktuell nicht statt. =Installation= Den Inhalt der ZIP-Datei einfach in den ULP-Ordner von EAGLE kopieren, dann mit "run bom" ausführen oder übers Menü Datei -> Exportieren -> BOM. =Download= [[Datei:eagle_bom.zip]] ==Änderungen== ===2018-08-09: Version 1.11=== Support für MediaWiki-Tabellen hinzugefügt ===2019-02-10: Version 1.12=== Support für JSON hinzugefügt [[Kategorie:Sonstiges]] [[Kategorie:Software]] [[Kategorie:Kleine Helferlein]] [[Kategorie:EAGLE]] f3da15c53aa11865fa1a16adbffb01d9abbe1b3c EAGLE-BOM für MediaWiki 0 531 1234 2019-02-10T21:18:24Z Qsysopr 1 Qsysopr verschob die Seite [[EAGLE-BOM für MediaWiki]] nach [[EAGLE-BOM]]: wird bisschen universeller ;) wikitext text/x-wiki #WEITERLEITUNG [[EAGLE-BOM]] 63dafa9f114726d610ecea16b93c9870b8d5d705 Datei:Eagle bom.zip 6 532 1236 2019-02-10T21:27:42Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Pirozeda-HAT 0 533 1239 2019-02-10T21:34:53Z Chris 2 Aus Artikel [[Pirozeda]] extrahiert wikitext text/x-wiki =Pirozeda-HAT= Wie bereits weiter oben und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADMUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar geschmackssache aber in Hinblick auf Platz das beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. '''ACHTUNG: Die Hardware ist bis jetzt weder aufgebaut noch getestet. Leiterkarten sind auf dem Weg zu mir.''' ==Bestückungsvarianten== Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ===Variante 1: Direkt=== Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist dass neben der gemeinsamen Masse mit der Solaranlage Backfeeding entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Die Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ===Variante 2: Optokoppler=== Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit Optokoppler </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || R13 || 1k || R0603 || RND 0603 1 470 |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ===Variante 3: ADUM-Isolator=== Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || R9, R10 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Bestückungsoptionen== Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ===Option: HAT-ID=== Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEPRom ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 6 || C6 || 100n || C0603 || X7R-G0603 100N |} Aktuell gibt es noch keine weitere Unterstützung hierfür. ===Option: Real-Time-Clock=== Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 4 || R5, R6, R7, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 2 || Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. ===Option: I²C(-OLED) + Taster=== Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |} ===Option: Status-LEDs=== Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. ==Firmware== Grundsätzlich läuft die Firmware des original-Adapters auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel. [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 88512c46f41a95fe671ece9ce3402306ac5c92b0 1240 1239 2019-02-10T21:37:11Z Chris 2 unnötige Überschriften entfernt wikitext text/x-wiki Wie bereits im [[Pirozeda|Hauptartikel] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADMUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar geschmackssache aber in Hinblick auf Platz das beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. '''ACHTUNG: Die Hardware ist bis jetzt weder aufgebaut noch getestet. Leiterkarten sind auf dem Weg zu mir.''' =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist dass neben der gemeinsamen Masse mit der Solaranlage Backfeeding entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Die Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit Optokoppler </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || R13 || 1k || R0603 || RND 0603 1 470 |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || R9, R10 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEPRom ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 6 || C6 || 100n || C0603 || X7R-G0603 100N |} Aktuell gibt es noch keine weitere Unterstützung hierfür. ==Real-Time-Clock== Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 4 || R5, R6, R7, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 2 || Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. ==Option: I²C(-OLED) + Taster== Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |} ==Status-LEDs== Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. ==Firmware== Grundsätzlich läuft die Firmware des original-Adapters auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel. Eine auf die neue Hardware angepasste Firmware ist aktuell in Arbeit. [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] c1632c6ccc407758848c6fcc6a0f8f81977b0d66 1241 1240 2019-02-10T21:39:11Z Chris 2 Hinweise zur Verifikation hinzugefügt wikitext text/x-wiki Wie bereits im [[Pirozeda|Hauptartikel]] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADMUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar geschmackssache aber in Hinblick auf Platz das beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== '''Noch nicht aufgebaut und getestet''' Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist dass neben der gemeinsamen Masse mit der Solaranlage Backfeeding entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Die Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== '''Aufgebaut und erfolgreich getestet''' Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit Optokoppler </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || R13 || 1k || R0603 || RND 0603 1 470 |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== '''Noch nicht aufgebaut und getestet''' Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || R9, R10 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEPRom ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 6 || C6 || 100n || C0603 || X7R-G0603 100N |} Aktuell gibt es noch keine weitere Unterstützung hierfür. ==Real-Time-Clock== Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 4 || R5, R6, R7, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 2 || Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. ==Option: I²C(-OLED) + Taster== Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |} ==Status-LEDs== Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. ==Firmware== Grundsätzlich läuft die Firmware des original-Adapters auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel. Eine auf die neue Hardware angepasste Firmware ist aktuell in Arbeit. [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 81f4e628a06a250672ae59e75e81c962287ca8fc 1244 1241 2019-02-10T21:44:21Z Chris 2 Formatierung korrigiert wikitext text/x-wiki Wie bereits im [[Pirozeda|Hauptartikel]] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADMUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar geschmackssache aber in Hinblick auf Platz das beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== '''Noch nicht aufgebaut und getestet.''' Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist dass neben der gemeinsamen Masse mit der Solaranlage Backfeeding entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Die Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== '''Aufgebaut und erfolgreich getestet.''' Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit Optokoppler </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || R13 || 1k || R0603 || RND 0603 1 470 |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== '''Noch nicht aufgebaut und getestet.''' Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || R9, R10 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R14, R15, R16, R23 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== '''Aufgebaut und erfolgreich getestet.''' Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEPRom ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 6 || C6 || 100n || C0603 || X7R-G0603 100N |} Aktuell gibt es noch keine weitere Unterstützung hierfür. ==Real-Time-Clock== '''Aufgebaut und erfolgreich getestet.''' Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 4 || R5, R6, R7, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 2 || Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. Der Levelshifter kann nach ersten Testes getrost weggelassen werden. ==Option: I²C(-OLED) + Taster== '''Noch nicht aufgebaut und getestet.''' Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge|| Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |} ==Status-LEDs== '''Aufgebaut und erfolgreich getestet.''' Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. ==Firmware== Grundsätzlich läuft die Firmware des original-Adapters auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel. Eine auf die neue Hardware angepasste Firmware ist aktuell in Arbeit. [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] db4eb285b5a287f48fc38223d58859e17db75710 Prozeda-Decoder 0 460 1245 1148 2019-02-10T21:45:42Z Chris 2 Kategorie wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FT2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Einblick in den Regler= Ein Griff in die Zukunft - 11/2017: Im Rahmen der [[Pirozeda]]-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen: <gallery> sungo_sxlplus.JPG | SUNGO SXLplus von außen sungo_sxlplus_ctrl_top.jpg | Controllerboard vorne sungo_sxlplus_ctrl_bot.jpg | Controllerboard hinten sungo_sxlplus_pwr_top.jpg | Leistungsboard vorne sungo_sxlplus_pwr_bot.jpg | Leistungsboard hinten sungo_sxlplus_pwr_port.jpg | Anschluss des Datasticks sungo_sxlplus_pwr_switch.jpg | Schaltmodule </gallery> ==Controllerboard== Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte. Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war. Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt. Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt... ==Leistungsboard== So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen. Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter. Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder. Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können. =Der Datenstick= Wie bereits erwähnt verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} ==Datenformat== Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <source lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </source> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ===Speichersegmente=== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ===Systeminfo=== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ===Spaltenbeschreibung=== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ===Loggingdaten=== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <source lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </source> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <source lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </source> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <source lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </source> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 7fcd359bb1d47c1727972e1a3c7c42e1b603a067 Kategorie:Pirozeda 14 534 1246 2019-02-10T21:47:35Z Chris 2 Die Seite wurde neu angelegt: „Pirozeda, der. Ein Wortkonstrukt aus (Raspberry) Pi und Prozeda. Dabei handelt es sich um die Anbindung des [Prozeda-Decoders] an den Kategorie:Raspberry P…“ wikitext text/x-wiki Pirozeda, der. Ein Wortkonstrukt aus (Raspberry) Pi und Prozeda. Dabei handelt es sich um die Anbindung des [Prozeda-Decoders] an den [[Kategorie:Raspberry Pi]]. 44de5dffdfd6d92d938872fa8b2dac1b024db5c9 1247 1246 2019-02-10T21:48:04Z Chris 2 Eh? wikitext text/x-wiki Pirozeda, der. Ein Wortkonstrukt aus (Raspberry) Pi und Prozeda. Dabei handelt es sich um die Anbindung des [[Prozeda-Decoders]] an den [[Kategorie: Raspberry Pi]]. [[Kategorie:Raspberry Pi]] 0d96924206ae90b2c39d6c0460b965f793b5d453 1248 1247 2019-02-10T21:49:13Z Chris 2 Funktioniert der Kategorieverweis jetzt? wikitext text/x-wiki Pirozeda, der. Ein Wortkonstrukt aus (Raspberry) Pi und Prozeda. Dabei handelt es sich um die Anbindung des [[Prozeda-Decoders]] an den [[:Kategorie:Rasperry Pi]] a651730b2e6af0a53e6cb6605a88d9becee97eed 1249 1248 2019-02-10T21:50:04Z Chris 2 wenn man sich halt nicht vertippen würde... wikitext text/x-wiki Pirozeda, der. Ein Wortkonstrukt aus (Raspberry) Pi und Prozeda. Dabei handelt es sich um die Anbindung des [[Prozeda-Decoder]]s an den [[:Kategorie:Raspberry Pi|Raspberry Pi]] 86a7353b6f1d5232fe4cbafffbb493b7f9294f99 Lichtsensor Avago APDS-9300 0 428 1250 1154 2019-02-10T21:51:07Z Chris 2 Kategorie wikitext text/x-wiki Vor einiger Zeit (genau genommen noch im Studium) wollte ich mit Lichtsensoren (ambient light sensors, ALS) spielen. Da ich bei Farnell bestellen konnte, kamen zwei Avago APDS-9300 mit auf das Bestellformular (Mittlerweile auch beim blauen Claus bzw. Völkner zu haben). Aufgrund der Bauform und Zeitmangel blieben sie relativ lange in der ESD-Tüte. =Der Sensor= Was soll man groß Worte über einen Lichtsensor verschwenden? Licht rein, aufbereitetes Signal raus und gut ist. Ganz so einfach ist es (zumindest beim APDS-9300) leider nicht. Viele optische Sensoren drehen bei Infrarot wild, das menschliche Auge zeichnet sich dagegen als ziemlich unempfindlich aus. In Digitalkameras werden aus diesem Grund IR-Filter verbaut (die Astrofotografen wieder entfernen), allerdings scheint das den Entwicklern bei Avago entweder zu teuer oder zu unpraktisch gewesen zu sein - sie haben zwei Fotodioden verbaut: Eine ist empfindlich auf das sichtbare Licht und Infrarot, die andere nur auf Infrarot (siehe Seite 7 vom Datenblatt). Der Rest ist Mathematik. Da die menschliche Wahrnehmung weitestgehend logarithmisch ist, braucht man zur Nachbildung einen großen Dynamikumfang. Daher kann der ALS mehrere Betriebsmodi. Zum einen kann man die Integrationszeit (also die Zeit, in der die Lichtdosis gesammelt wird) wählen - konkret zwischen 13,7 ms, 101 ms und 402 ms. Zum anderen kann man einen 16-fach-Verstärker zuschalten. Dadurch gewinnt man zwar Empfindlichkeit, bezahlt die aber mit der Auflösung und Rauschen. Die Wahl der richtigen Einstellung hängt selbstverständlich von der Umgebungshelligkeit ab, ansonsten liest man entweder 0 oder der bekommt Werte in der Sättigung, die einfach keinen Sinn ergeben. =Hardware= Bei der Fertigung meiner ersten Fuhre Leiterkarten bei DirtyPCBs landete auch ein kleines Breakout-Board auf dem Panel: <gallery> Datei:apds9300_sch.png|Schaltplan, Datei:apds9300_brd.png|Layout Datei:apds9300_asy.jpg|und aufgebautes Sensormodul </gallery> Neben dem Sensor selbst befindet sich aufgrund dessen etwas unpraktischen Versorgungsspannung ein 2,5 V-LDO-Spannungsregler. Die Wahl auf den LDO fiel, damit die Schaltung neben den eher altmodischen 5 V auch bei 3,3 V (und somit zum Beispiel mit dem Raspberry Pi) funktioniert. Als Schnittstelle dient bei dem Lichtsensor I²C, die Treiberstufen sind hier zwar zwangsläufig Open Drain und können deshalb in aller Regel etwas höhere Spannungen als die Betriebsspannung ab, bei den Eingangstufen bzw. ESD-Schutz wird es für das Bauteil bei höheren Spannungen ungemütlicher. ==Levelshifter== Damit man den I²C mit höherer Spannung betreiben kann, wird ein (bzw. eher zwei) Levelshifter benötigt. Diesen kann man entweder fertig kaufen oder mit nur wenigen Bauteilen aufbauen - [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] erklärt, wie es funktioniert. Für alle, die zu faul zum Klicken oder des Englischen nicht ganz so mächtig sind: Bei der Schaltung wird sowohl die Body-Diode als auch die schaltende Wirkung des FET genutzt (und als Beifang die Pull-Up-Widerstände, die man für I²C eh braucht). Das Schaltungsprinzip ist einfach wie genial: Wird keine der beiden Seiten auf Masse gezogen, ist U_GS nahezu 0 oder zumindest weit unter U_GS,th - der FET sperrt und dadurch dass die Spannung auf der Kathoden-Seite der Diode höher als auf der Anoden-Seite ist, sehen sich die Schaltungsteile nicht. Den Rest erledigen die Pull-ups. Wird auf der 3,3 V-Seite das Signal auf Masse gezogen, steigt U_GS über U_GS,th und der Transistor beginnt zu leiten. Dadurch sieht man auf der 5 V-Seite die Masse der 3,3 V-Seite. Szenario Nummer 3 ist nicht ganz so offensichtlich: Wird die 5 V-Seite auf Masse gezogen, fällt zunächst der Drain-Pin des FETs auf Masse. Jetzt kommt ein Teil vom Transistor ins Spiel, der einem manchmal einen Knoten ins Gehirn macht: Die Body-Diode. Ist auf deren Kathoden-Seite ein niedrigeres Potenzial als auf deren Anoden-Seite, wird sie leitfähig, somit zieht sie den Source-Pin ebenfalls gegen die Masse, die auf der Source-Seite anliegt. Gegen - nicht auf - da noch ein bisschen Vorwärtsspannung abfällt. Allerdings fällt steigt auch U_GS über U_GS,th (der zweite Knoten im Gehirn) und der FET wird leitfähig. Somit ist die Masse der 5 V-Seite auf der 3,3 V-Seite (relativ) sauber sichtbar. Fertig ist der pillepalle einfache bidirektionale Levelshifter. Einziger Nachteil: die Spannung "links" muss immer kleiner sein als die "rechts". Zudem ist man mit den Spannungspegeln begrenzt (zum einen durch U_GS,th des FET und zum anderen durch die U_f der Body-Diode). Übrigens kann man durch das Abklemmen des Gates die Seite mit der niedrigeren Spannung isolieren. =Software - der erste Versuch= Wie kann man relativ einfach mit I²C basteln? Bei denen im PC kommt man zumindest unter Windows nicht ran (und will es [https://web.archive.org/web/20160506154718/http://www.paintyourdragon.com/?p=43 vermutlich auch nicht]), bei Mikrocontrollern muss man erst Soft- und Hardware basteln - das ist aufwändig und fehleranfällig. Was liegt also näher, als den Raspberry Pi zu verwenden? Dort gibt es neben den [https://github.com/groeck/i2c-tools i2c-tools] auch eine Integration in Python. Da ich keine besonderen Erfahrungen mit letztere Sprache habe, möge man mir die Codequalität entschuldigen. apds9300.py ist eine Klasse, die die Kommunikation mit dem Sensor beinhaltet. Mit viewapds.py wird der Sensor im Halbsekunden-Takt ausgelesen und sowohl die rohen als auch der berechnete Wert ausgegeben. So viel zur Theorie. In der Praxis verwandelte sich die Verwunderung sehr schnell in Verzweiflung - es kamen einfach keine auch nur halbwegs sinnvollen Werte heraus. Zuerst hatte ich meine kläglichen Versuche in Python im Verdacht, nach mehrmaligem Überprüfen und neu schreiben stellte sich allerdings heraus, dass anscheinend etwas mit dem Chip oder Datenblatt nicht passt, denn ein Vergleich mit [[wpde:Lux_(Einheit)#Beispiele_typischer_Beleuchtungsst.C3.A4rken typischen Werten|Beispielen]] in Wikipedia sagte mir nur: du liegst falsch. Nach ein paar Recherchen stellte sich heraus, dass der APDS-9300 auf einem anderen Sensor basiert (oder zumindest nicht verleugenbare Ähnlichkeiten besitzt), dem TS256x von TAOS. Auch der physische Aufbau hat gewisse Ähnlichkeiten (und die Formeln zur Berechnung der Helligkeit ebenfalls). Zudem hatten auch schon andere das Problem mit den Berechnungen, nur gab es keine Lösung. =Kalibrierung= Da hilft nur noch eines: Kalibrieren. Nur gegen was? Die Helligkeitswerte aus dem oben erwähnten Wikipedia-Artikel kann man nicht so einfach und vor allem nicht so genau nachstellen, also muss entweder eine kalibrierte Lichtquelle her oder Vergleichsmessungen gemacht werden. Es liegen ja genügend "Messgeräte" in Form von Handy und Tablet herum. Mit einer [https://play.google.com/store/apps/details?id=com.notquitethem.android.luxmeter passenden App] bekommt man die Helligkeit mundgerecht angezeigt, nur: bei meinen HTC (Sensation, Flyer und [http://hobbyelektronik.org/b/2013/02/transplantation-geglueckt-patient-muss-sterben/ Explorer]) kann man nur zwischen heller Sommertag, bedeckter Sommertag und Zappenduster unterscheiden. Das LG-Handy war in der interessanten Zeit in Reparatur und das Samsung-Tablet hatte zwar eine sehr hohe Auflösung aber dafür eine völlig unbrauchbare Winkelabhängigkeit. Ich habe mir sogar überlegt, mit der Fotokamera zu messen. Aber wie zum Henker kommt man von Blende, Belichtungszeit, Bildempfindlichkeit und Bildausschnitt auf einen brauchbaren Helligkeitswert in Lux? Nachdem die Granularität durch die festen Schritte bei den drei ersten Parametern recht schlecht ist und die Messung durch den Bildausschnitt noch heikler wird, habe ich es bei der Idee belassen. Es muss also ein geeignetes Messgerät her. Nur für das Vermessen eines Sensors Messequipment kaufen (das den Sensor auch gleich ersetzt)? Muss nicht sein: ==Minolta T-10== In der Arbeit ist u. a. ein portables Luxmeter vorhanden und ich durfte es mir freundlicherweise für zwei Wochenenden ausleihen. Das Teil hat eine RS-232-Schnittstelle, wenn auch mit einem etwas komischen Stecker. Nach der Protokollbeschreibung muss man etwas suchen, allerdings ist die Implementierung (abgesehen vom etwas verschwurbelten Ausgabeformat) relativ einfach zu bewerkstelligen. Wer in die Verlegenheit kommt, so ein T-10 (oder vergleichbare Modelle) auszulesen: unten in den Downloads gibt es sowohl für Python als auch C# Quelltexte. ==Versuch 1== Der Messaufbau umfasst: * ALS und Luxmeter (über USB-RS232-Wandler) am Pi * eine windig zusammengebaute Lichtquelle aus LED-Streifen, Kühlkörper und Diffusor aus einem alten Notebook-Display. * Ein Rigol DP832 als Spannungsquelle * Eine Metallschiene sowie ein Pappkarton zum Aufbauen eines "Lichtgalgen" Beide Lichtsensoren (Minolta und mein Kalibrierkandidat) wurden auf gleiche Ebene gebracht (wichtig!) und fixiert. Das Netzteil kann Spannungs- und Stromsweeps, die für solch einen Zweck auf den ersten Blick perfekt geeignet sind. Also den Strom von 0 bis IIRC knapp 1,5 A in 400 Schritten zu je 2 Sekunden durchlaufen lassen, das Messgerät und Sensor mit etwas höherer Frequenz abfragen und in eine Log schreiben lassen. Das Ganze mit allen möglichen Konfigurationen des ALS. Excel auf dem großen PC macht den Rest. Naja, denkste. Die Helligkeit ging alles andere als linear hoch. Die Daten habe ich direkt weggeworfen und die Messung erneut mit Variation Spannung laufen lassen - entgegen dem allgemeinen Glauben ging die Helligkeit linear hoch. Trotzdem ist und bleibt die Regel: LEDs über Stromquellen versorgen. Die Gründe breite ich hier jetzt nicht aus. Dort die beiden Helligkeitswerte im X-Y-Diagramm auftragen lassen und feststellen, dass der Sensor fernab von dem ist, was zu erwarten ist. Genauso sind die Daten in der Hinsicht etwas ungeschickt zum Auswerten, dass es für jede tatsächliche Helligkeit mehrere Wertepaare gibt. Gleichzeitig gibt es aber auch (erwartungsgemäß) ungültige Wertpaare, da ein Sensor vor und der andere nach dem Umschalten der Spannung ausgelesen wurde. Die ganzen Messartefakte kann man zwar filtern, aber das ist unnötig und nervig. Nachdem die ganzen Messungen durch waren, musste das Luxmeter auch schon wieder zurück in die Arbeit. Nachdem der erste Lauf vielversprechend war, glaube ich, dass die anderen Messungen ok waren. Zudem war es viel zu heiß (Sommer 2015), um im Büro zu sitzen. Long story short: ein kleiner Programmierfehler und die Integrationszeiten wurden nicht in den Sensor geschrieben. <gallery> Datei:apds9300_diag_1_1.png|Verstärkung = 1; Integrationszeit = 13,7ms Datei:apds9300_diag_1_2.png|Verstärkung = 16; Integrationszeit = 13,7ms </gallery> Aarrgghh! ==Versuch 2== Fehler darf man machen, solange man daraus lernt. Das Rigol kann USB, und für das Auslesen des ALS habe ich eine Schaltung mit dem [http://hobbyelektronik.org/b/2015/09/mcp2221/ MCP2221] aufgebaut. Die Lichtquelle bleibt die selbe, sie steckt aber nun in der Decke eines Schuhkartons. Dadurch kann der Abstand, Position und Helligkeit (Streulicht!) relativ gut definiert werden: <gallery> Datei:apds9300_box.jpg|Aufbau der Messbox </gallery> Software: Dieses Mal in C#. Das kenne ich halbwegs und mag es. ===Automatisierung=== Zur Ansteuerung vom Netzteil muss erst einmal [https://www.ni.com/visa/ NI VISA] installiert werden. Ich hasse es, ich liebe es. Ich hasse es, weil die VISA-Treiber ein riesiges Bollwerk sind und man beim ersten Versuch immer die falschen erwischt. Zudem gibt es einen schönen Bug, bei dem Windows nach deren Installation irgendwann anfängt, knapp 20 Minuten für den Login zu braucht. Den [http://digital.ni.com/public.nsf/allkb/814FEF952915137686257B6B006C5F4F?OpenDocument offiziellen Fix] habe ich selbst noch nicht getestet, mit der im [http://forums.ni.com/t5/LabVIEW/Issues-with-windows-7-after-Labview-2012-installation/m-p/2257858#M715816 NI-Forum] beschriebenen Vorgehensweise habe ich gute Erfahrungen gemacht. Dadurch macht man sich unter Umständen zwar [[wpde:LAN eXtensions for Instrumentation|LXI]] kaputt, was in den meisten Fällen eh nicht verwendet wird. Was ich an VISA liebe? [[wpde:SCPI|SCPI]]! Messautomatisierung ist etwas wirklich feines und nicht nur, weil man auf dem Weg in die Mittagspause noch kurz "MAHLZEIT" auf dem Multimeter anzeigen lassen kann. Mir hat es in der Arbeit bereits unbeschreiblich viel manuelle Messzeit erspart. Dazu kommt, dass die Wiederholbarkeit sehr gut ist. Wie auch immer, die Software ist schnell und hässlich - aber zweckmäßig - runtergerissen. Die Messungen sind zum Einstellen der Helligkeit der Lichtquelle synchronisiert und neben den deutlich besseren Ergebnissen kann ich zugleich meine Lichtquelle kalibrieren. Ein Messlauf dauert nicht ganz zwei Minuten, wegen der unterschiedlichen Integrationszeiten und den beiden möglichen Verstärkungsfaktoren mal 6 und schon hat man einen Sensor vermessen. ==Auswertung== Das ganze nochmal in Excel verwurstet und es sieht gar nicht mal so gut aus: <gallery> Datei:apds9300_diag_2_1.png|Messergebnisse 1. Sensor mit Gain = 1 Datei:apds9300_diag_2_2.png|Messergebnisse 1. Sensor mit Gain = 16 </gallery> Im ersten Diagramm sieht man, dass die Werte schön und nahezu linear nach oben gehen, allerdings ist da - je nach Integrationslänge ordentlich Faktor drauf. Bei der Ausgabe wurde die Integrationszeit nicht berücksichtigt. Die Einbrüche im zweiten Diagramm lassen sich durch die tatsächlichen Messwerte erklären: <gallery> Datei:apds9300_diag_2_3.png|Messwerte ohne und 16-facher Verstärkung </gallery> Kanal 0 geht bei 16-facher Verstärkung sehr früh in Sättigung - das ist alles. Ok, nun müssen die Helligkeitswerte noch richtig skaliert werden. Meine Vermutung geht stark in die Richtung, dass entweder die Lichtempfindlichkeit oder die Integrationszeit bei den Sensoren nicht ganz richtig sind. Man kann den Korrekturfaktor zwar auf die berechnete Helligkeit anwenden - dadurch dass es in den Berechnungen keine Offsets gibt, sollte das auch funktionieren. Mir ist es allerdings deutlich lieber, direkt die rohen Werte zu behandeln. Also die Messwerte skalieren, durch die Formel zur Berechnung der Helligkeit jagen und das Ergebnis vergleichen. Excel kann das relativ gut automatisch - mit der Zielwertsuche. Der Parameter dafür ist die prozentuale Abweichung der berechneten Helligkeit und der Referenzmessung vom Luxmeter. Damit das Ganze funktioniert, muss der Algorithmus zur Berechnung in Excel implementiert werden. Ich habe aufgehört zu zählen... Unter Berücksichtigung der Integrationszeiten ergibt sich ein Faktor von relativ genau 0,2, um auf die "richtige" Helligkeit zu kommen. Zum Vermessen des zweiten Sensors habe ich diesen Faktor für die Berechnung des ausgegebenen Wertes in meine Software eingetragen und es kommt relativ gut hin - über den kompletten Messbereich war die Abweichung nicht größer als 5 %. Selbstverständlich ist das statistisch nicht aussagekräftig aber trotzdem eine Bestätigung, dass die ganze Aktion nicht grob falsch war. Die Erkenntnisse sind auch direkt in die C#-Software gewandert. Mit dieser kann im aktuellen Zustand die Helligkeit angezeigt werden. ="Kalibrierung" der Lichtquelle= Das Luxmeter musste ich selbstverständlich zurückgeben, aber was nun, wenn plötzlich und völlig unerwartet wieder ein Lichtsensor auf dem Tisch liegt und getestet werden muss, ob er richtig liegt, wenn das Licht angeht? Warum nicht einfach schauen, wie stabil die Lichtquelle ist? Natürlich ist der 15-Minuten-Aufbau nichts, was man für professionelle Zwecke auch nur in Erwägung ziehen würde, aber für den Heimbedarf - und um einen groben Anhaltspunkt zu finden: warum nicht? LEDs verändern sich in ihrem Leben. Wie sie bei Umgebungstemperatur altern: da habe ich kein wirkliches Gefühl. Allerdings weiß ich sehr genau, dass sie mit der Betriebszeit und durch Temperatur altern. Zugleich können sie ihre momentane Ausbeuten durch Erwärmung verändern. Da der Aufbau vermutlich nur für kurze Tests verwendet werden soll, kann die "Abnutzung" durch Betriebsdauer vernachlässigt werden. Anders ist es bei der Veränderung durch Betriebstemperatur. Allerdings kann man das relativ einfach testen: LEDs auf maximaler Leistung betrieben, Lichtsensor darunter packen und während den laufenden Messungen warten. Nach gut 20 Minuten (Länger ist das Ding wahrscheinlich eh nie am Stück im Betrieb) tat sich: nichts. Die LEDs sind offensichtlich stabil genug - oder die Messeinrichtung zu ungenau. Wer weiß. Auf jeden Fall habe ich jetzt eine zumindest grob brauchbare Ergebnisse, falls mal wieder ein Sensor vermessen werden will. =Leiterkarten= Ein paar der oben gezeigten Leiterkarte sind noch übrig. Wer will, kann eine haben. =Downloads= * [[Datei:apds9300.zip]] Alle Sourcen und Messdaten samt Auswertung. [[Kategorie:Elektronik]] [[Kategorie:PC]] [[Kategorie:Sensor]] [[Kategorie:Raspberry Pi]] 3f8e923665368d5246d0e0c32b6d94cd5dea6eaf Datei:Resol nano 0.1 assy.jpg 6 535 1251 2019-02-11T21:47:37Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol nano 0.1 meas falling.png 6 536 1252 2019-02-11T21:47:46Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol nano 0.1 meas rising.png 6 537 1253 2019-02-11T21:47:54Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol nano 0.1 meas threshold.png 6 538 1254 2019-02-11T21:48:02Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol nano 0.1 noise.png 6 539 1255 2019-02-11T21:48:10Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol nano 0.1 noise zoom.png 6 540 1256 2019-02-11T21:48:19Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder 0 120 1257 1232 2019-02-11T21:48:54Z Chris 2 /* VBus-Adapter Nano */ Foto der Leiterkarte und Messergebnisse hinzugefügt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_threshold.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] cc384fcf6010dfd4b27daf0875abe3aeb0c46db3 1258 1257 2019-02-11T21:49:45Z Chris 2 /* Messung */ Screenshot korrigiert wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] bce411dfa53add6697085389ef5ff8d23a544e83 1260 1258 2019-02-11T21:52:59Z Chris 2 Kategorie wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] <strike>Manche Felder sind falsch oder an der falschen Stelle. Im Vergleich zum Resol ServiceCenter (in Klammern) ergibt sich folgendes:</strike> *<strike>Temperatursensor 12 zeigt 0.0 an (888.8 - unbelegt)</strike> ** Grund war, dass ich zählen konnte. (0-12 anstatt 0-11 bzw. 1-12) *<strike>Sensorbruchsmaske ist 0 (4024)</strike> **Offset des Feldes war falsch *<strike>Sensorkurzschlussmaske und Sensorbenutzungsmaske sind vertauscht</strike> **wie oben *<strike>Negative Temperaturen werden falsch angezeigt (kann aber auch an itoa liegen)</strike> **Hätte schon funktioniert, wenn man allerdings die Zahl vor itoa durch 10 teilt... (jetzt wird es richtig angezeigt, da vorher ein Zweierkomplement gemacht wird) Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *<strike>Ziel der Daten (vbus_outdata) durch Pointer definierbar</strike> **erledigt *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 18abb45020ae45bd4de9c34522a73e690ed9862f 1294 1260 2019-02-17T21:01:15Z Chris 2 Hinweise zum Aufbau wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 012cc31060c99fbd1c96ea33e393b07c91b1a1dc 1295 1294 2019-02-24T15:04:47Z Chris 2 /* VBus-Adapter Nano */ FAQ hinzugefügt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==FAQ== * Ist der Adapter mit allen Resol- bzw. Viessmann-Anlagen kompatibel Vermutlich nein. Manche Resol-Anlagen verwenden wohl RS-485. Ein Indiz für die Kompatibilität ist die Angabe in der Anleitung, dass die Schnittstelle Strom zur Verfügung stellt. * Kann der Adapter direkt an einem Single-Board-Computer (z. B. Raspberry Pi) verwendet werden? Ja. Bisher wurde die Schaltung mit 3,3 und 5 V auf der Sekundärseite getestet. Für 1,8 V I/O-Spannung kann ich noch keine Aussage machen. * Gibt es Software für Single-Board-Computer oder den PC? Nein, noch nicht. Aber es steht auf der (langen) TODO-Liste. * Kann der Adapter direkt am PC betrieben werden? Es kommt darauf an. Sowohl für USB als auch RS-232 (klassischer COM-Port) wird ein Adapter benötigt. Für USB tut es ein USB-UART-Adapter (die man z. B. zum Bespielen von Arduinos kennt, Beispiel FT232), für RS-232 muss ein Pegelwandler (z. B. MAX2232) zwischengeschaltet werden. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 084be38861c69dec9318c33d11f36db73c0b12fb Hauptseite 0 1 1259 1237 2019-02-11T21:52:07Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano-Adapter]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] b4ad8a65fb0536c494636e1becfb38b828c1aa93 1262 1259 2019-02-11T21:54:42Z Chris 2 Weniger Adapter reicht auch wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] a9e6d2d72145a29a80aaa56750449d49ce16a9df ECL-Bus-Decoder 0 225 1261 642 2019-02-11T21:53:52Z Chris 2 Kategorie wikitext text/x-wiki Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: == Busteilnehmer == {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} === ECL 300 === [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Das/Der ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. Auf der Vorderseite befindet sich eine Diagnoseschnittstelle, die als RS232 mit 1200 Baud, 8 Bit, Odd Parity und 2 Stoppbits spricht. Der Stecker ist ein RJ12 (6P6C), die Anschlussbelegung für den PC lautet wie folgt: {| class="wikitable" |- ! RJ12 !! Sub-D |- | 4 Rx || 3 |- | 5 Tx || 2 |- | 7 GND || 5 |} Achtung: Die Zählweise beim RJ12-Stecker beginnt bei 2. Aufgrund der mäßigen Beschreibung im Datenblatt kann es sein, dass die Belegung gespiegelt ist (werde ich noch prüfen) Das Auslesen findet "aktiv" statt, d. h. man muss Werte abfragen - der Regler sendet von sich aus nichts. Zum Abfragen der Temperaturen muss man 0xCE <addr> 0x00 0x00 <checksum> senden. Für die Checksum muss man alle gesendeten Bytes ver-XOR-en, für die Temperaturen also einfach 0xCE ^ addr. {| class="wikitable" |- ! Adresse !! Anschluss |- | 0xFA || B8 |- | 0x32 || B5 |- | 0x34 || B4 ? |- | 0xF8 || B3 ? |- | 0xFC || B7 ? |- | 0x38 || B2 |- | 0x3C || B1 |} [http://de.fernwaerme.danfoss.com/xxTypex/17613_MNU17407525_SIT21.html Produktseite bei Danfoss] === ECA 86 === [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt [http://de.fernwaerme.danfoss.com/Product/087B1158_MNU17407526.html Produktseite bei Danfoss] === ECA 60 === [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEProm 93C66A (512x8 bit) gespeichert. [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407525.html Produktseite bei Danfoss] == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung !! Häufigkeit |- | AF || 04 || Innentemperatur (ECA 60) || 125/h |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || -- |- | AF || 09 || Abfrage Tagesprogramm || 63/h |- | AF || 11 || Zeit setzen || -- |- | EF || 60 || Temperaturfühler ECA 86 || 125/h |- | F0 || 01 || Außentemperatur || 125/h |- | F0 || 02 || Aktuelle Zeit || 125/h |- | FA || 05 || Solltemperatur am ECL 300 setzen || -- |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) || -- |- | FA || 09 || Tagesprogramm (Antwort auf AF06) || 63/h |- | FE || 62 || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine Stunde, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. Die Positionsangaben b[x] beziehen sich auf den 0-basierenden Index im Paket, die Angabe "das x-te Byte" auf die 1-basierende Position. Das Byte zu Beginn eines Pakets ist also b[0] und wird mit "1. Byte" bezeichnet. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 Temperatur </pre> Im 4. Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im dritten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[3] + b[2]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger (siehe Diagramm). === AF05/FA05/FF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? !!!!!!!0 !!!!!!!0 ?0000!!! Soltmp. Abw.tmp. Modus </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das dritte Byte (b[2]) bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. ==== Solltemperatur ==== Im 5. Byte befindet sich die Solltemperatur um ein Bit verschoben (b[3] >> 1). ==== Abweichende Temperatur ==== Im 6. bzw. 7. Byte ist die Abweichung zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gültig ist. Im Modus "Entspannen" wird die Abweichung in b[5] gespeichert, bei "Abwesenheit" in b[6]. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Um echte 8-Bit-Integer verwenden zu können, werden im Code die fehlenden Bits ersetzt: <pre> if(type == ECL_DIFF_RELAX) { ecl_data.tmp_diff = buff[5] >> 1; if(ecl_data.tmp_diff & 0x20) { ecl_data.tmp_diff |= 0xC0; } } else if(type == ECL_DIFF_AWAY) { ecl_data.tmp_diff = buff[6] >> 1; if(ecl_data.tmp_diff & 0x40) { ecl_data.tmp_diff |= 0x80; } } </pre> Das Setzen einer Abweichungen ist etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern. ==== Betriebsart ==== Das letzte (8.) Byte zeigt an, in welcher Betriebsart sich der Regler befindet. {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Handbetrieb |- | 001 || 1 || Zeitgesteuerter Betrieb |- | 010 || 2 || Konstante Komforttemperatur |- | 011 || 3 || Konstante reduzierte Temperatur |- | 100 || 4 || Standby |} Die restlichen möglichen Stati sind mir nicht bekannt. === AF06/FA06 (Bestätigung Solltemperatur) === Dieses Paket dient anscheinend der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (FA06 folgt auf AF05 bw. AF06 folgt auf FA05) direkt nach einem **05-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden. === AF09/FA09 (Tagesprogramm) === Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen. Um diese Daten zu erhalten, muss es folgendes auf den Bus legen: <pre> AF09 00000010 00000000 00000000 00000000 00000000 00000000 00000!!! 00000000 00000000 00000000 00000000 00000000 Tag </pre> Die untersten 3 Bit des dritten Byte entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6. Der ECL300 antwortet dann wie folgt: <pre> FA09 00001111 11111111 11111111 11111111 11110000 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ^ 23:30 00:00 ^ </pre> Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet. In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr. === AF11/F002 (Zeit setzen/Aktuelle Zeit) === <pre> F002 *** TODO *** 0!!!!!!! 0!!!!!!! 00!!!!!!! 00!!!!!! !!!!!!!! !!!!!!!! Sekunde Minute Stunde Tag Jahr WTagMona </pre> Die Uhrzeit ist einfacher aufgebaut, als man Denkt. In den Bytes folgen aufeinander die Sekunde (b[2]), Minute und Stunde des aktuellen Tags. Der aktuelle Tag wird im 6. Byte gespeichert, das 8. Byte enthält im höherwertigen Nibble den aktuellen Wochentag (TODO: welcher ist nochmal der erste?) und im niederwertigen den aktuellen Monat (1-12). Das Jahr (b[6]) ist relativ zum Jahr 1900 notiert. Um den "korrekten" Wert zu erhalten, muss man zu dem empfangenen Byte einfach 1900 addieren. === EF60 (Temperatursensoren ECA86) === <pre> EF60 10000001 00011110 01101000 00001001 00100011 00000000 EF60 01110101 00011111 00000000 01100000 01000101 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! 00000000 Temperatur Bx/x Temperatur Bx/x Index </pre> Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt. Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes nach der Adresse, der zweite in den beiden darauf folgenden. Das 7. Byte gibt an, um welche Werte es sich handelt. === F001 (Außentemperatur) === <pre> F001 *** TODO *** !!!!!!!! ?!!!!!!! ???????? !!!!!!!! ???????? ???????? Temperatur Modus </pre> In den beiden Bytes nach der Adresse steht - im gleichen Schema wie die Innentemperatur - Kodierte Außentemperatur. Im 6. Byte stehen die Modi für die beiden Heizkreise. Das die oberen 4 Bit repräsentieren hier den Brauchwasserkreis, die unteren 4 den Heizkreis. {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Reduzierte Temperatur |- | 01 || 1 || Optimierte Aufheizphase |- | 10 || 2 || Komforttemperatur |- | 11 || 3 || Optimierte Absenkphase |} Selbst miterlebt habe ich nur Modus 0 und 2, die anderen beiden entstanden aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet. Was mit den restlichen 12 möglichen Stati ist, weiß ich nicht. === FE62 (Setzen Relais an ECA 86) === == Prüfsumme == Wie bereits im [http://hobbyelektronik.org/b/?p=415 Blog] bemängelt ist die Prüfsumme nicht allzu solide. Sie wird berechnet, indem alle Bytes des Pakets exklusive der vorletzten beiden miteinander addiert (!) werden und mit 0xFF verundet werden. Diese "Prüfsumme" entspricht dem vorletzten Byte des Pakets, wobei es manchmal vorkommt, dass das MSB gekippt ist (näherer Grund ist noch unbekannt). Das letzte Paket im Byte ist immer 0x0D, was zur Synchronisierung verwendet werden kann. == Was fehlt noch? == === Störung === Seitdem ich die Daten erfasse hatte ich leider/zum Glück noch keine Störung der Anlage. Ich könnte sie zwar am Alarmmodul künstlich erzeugen, war bisher aber noch nicht mutig/dumm genug. Laut Installateur werden Störungen auf dem ECA60 angezeigt, deshalb liegt sehr nahe, dass diese auch über den Bus übertragen werden. === Aktives Auslesen === Dass das aktive Auslesen von Parametern funktioniert, zeigt das ECA 60 mit dem aktuellen Tagesprogramm. Geht das auch mit anderen Werten? = Firmware = {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = CB | FuseL = FD }} Die Firmware für AVRs (oder besser gesagt C-Code) belegt einen Pin- (INT0) und einen Timer-Interrupt (TIMER0), mit denen das Signal vom ECL-Bus gesampelt wird. Die ISRs hierfür können in jeder beliebigen C-Datei stehen. die aufgerufenen Funktionen werden vom Compiler inline eingefügt. Damit das ohne zusätzlichen Speicherplatz funktioniert, musste ich (da ich es zugegebenermaßen nicht besser weiß), den Code fürs Sampeln in die H-Datei des Decoders einfügen. (Wer eine bessere/richtige Methode kennt, ich freue mich über Feedback!) In der Main-Schleife des Programms muss zusätzlich ecl_decode() aufgerufen werden, welche das zuletzt empfangene Paket auswertet und in die Variable ecl_data schreibt. Die Funktion sollte alle 8-12ms aufgerufen werden, damit kein Paket verpasst wird. Hier könnte noch etwas Optimierungsbedarf bestehen. Die Praxis wird zeigen, wie (un)günstig die aktuelle Einlesemethode ist. Um flexibel zu bleiben, verwendet der Code einige Präprozessoranweisungen, über die die einzulesenden Daten sowie Speicherbelegung beeinflusst werden können. Über die Konfiguration kann auch das Debugging konfiguriert werden. Die Beschaltung ist - wie oben weiter oben zu lesen - sehr einfach. Der ECL-Bus wird über einen Optokoppler galvanisch getrennt. Der Kollektor des Optos wird über einen Pull-Up nach oben gezogen (der AVR-interne dürfte hierfür reichen, momentan wird ein externer vorausgesetzt) und das Signal an PD2 (INT0) weitergegeben. In der Standardkonfiguration lässt der Code nur eine an PD6/PD7 gegen Masse angeschlossene Duo-LED (Grün an PD6, Rot an PD7) je nach empfangenem Paket/Status kurz aufleuchten. Konkrete Daten erhält man, wenn man das rudimentäre Debugging aktiviert und am UART bei 19200 Baud 8N1 lauscht. = Download = [[Datei:ECLBus.zip]] Version 0.1, AVR-Studio-Projekt [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Reverse Engineering]] 3ef4ca8b83078cb2e1484b26030de5f883d21c5f Datei:Flat cw packet.png 6 541 1263 2019-02-17T18:51:55Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer.jpg 6 542 1264 2019-02-17T18:52:06Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer assy back.jpg 6 543 1265 2019-02-17T18:52:23Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer assy back2.jpg 6 544 1266 2019-02-17T18:52:29Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer assy front.jpg 6 545 1267 2019-02-17T18:52:37Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer pcb assy.jpg 6 546 1268 2019-02-17T18:52:45Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer pinout erf32mg1.png 6 547 1269 2019-02-17T18:53:50Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer rev i2c.jpg 6 548 1270 2019-02-17T18:54:00Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer rev i22 flat ccw.png 6 549 1271 2019-02-17T18:54:14Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer rev i2c comm.zip 6 550 1272 2019-02-17T18:54:14Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer rev i22 flat cw.png 6 551 1273 2019-02-17T18:54:20Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer rev pinmap.jpg 6 552 1274 2019-02-17T18:54:29Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri gu10 back.jpg 6 553 1275 2019-02-17T18:54:41Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri gu10 front.jpg 6 554 1276 2019-02-17T18:54:47Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri gu10 front open.jpg 6 555 1277 2019-02-17T18:55:00Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri gu10 heatsink.jpg 6 556 1278 2019-02-17T18:55:04Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri gu10 module open.jpg 6 557 1279 2019-02-17T18:55:16Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri gu10 pcb angle.jpg 6 558 1280 2019-02-17T18:55:27Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri gu10 pcb bot.jpg 6 559 1281 2019-02-17T18:55:33Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri gu10 pcb nohipot.jpg 6 560 1282 2019-02-17T18:55:37Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri gu10 rf module.jpg 6 561 1283 2019-02-17T18:55:43Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri remote.jpg 6 562 1284 2019-02-17T18:55:47Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri remote frontplate.zip 6 563 1285 2019-02-17T18:56:00Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri remote jaeger.jpg 6 564 1286 2019-02-17T18:56:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri remote jaeger render.png 6 565 1287 2019-02-17T18:56:12Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Ikea Trådfri 0 566 1288 2019-02-17T18:57:26Z Chris 2 Artikel erstellt wikitext text/x-wiki Trådfri, wie es aussieht kein richtiges [https://sv.wiktionary.org/wiki/Tr%C3%A5dfri schwedisches Wort], das für das drahtlose Beleuchtungssystem von Ikea steht. Da ich mittlerweile ein paar Lampen aus dem Möbelhaus bei mir im Einsatz habe, wollte ich mich ein wenig damit auseinandersetzen Anmerkung: Einige Teile des Artikels sind aus dem [//hobbyelektronik.org/b/2018/05/teardown-von-tradfri/ Blog übernommen] =Kabelloser Dimmer 003.478.31= [[Datei:tradfri_dimmer.jpg|thumb|Tradfri Dimmer, nahezu unsichtbar auf weißem Grund]] ==Teardown== Nimmt man das "User-servicable" Gehäuse vom Dimmer ab, bekommt man folgendes zu Gesicht: <gallery> tradfri_dimmer_assy_back2.jpg|Dimmer, innen von hinten tradfri_dimmer_assy_front.jpg|Dimmer, innen von vorne </gallery> Die Typenbezeichnung ist also neben der Ikea-Nummer ICTC-G-1. Obwohl das Gehäuse den Anschein macht, als wäre es Ultraschall-verschweißt, ist es nur geklipst. "Built to a price", das Schweißen wäre ein zusätzlicher Produktionsschritt und die Spritzguss muss sowieso ran. Mit einem vorsichtig angesetztem Schraubendreher lassen sich die Gehäuseteile trennen und die Leiterkarte kommt zum Vorschein: <gallery> tradfri_dimmer_pcb_assy.jpg|Leiterkarte mit Batteriehalter tradfri_dimmer_assy_back.jpg|Mech. Batteriehalter und Taster </gallery> Das Rückteil ist weniger spektakulär – ein Magnet und eine Kontaktfeder für die Batterie. In der anderen Hälfte steckt die "Magie": <gallery> tradfri_dimmer_pcb_top.jpg|Bestückungsseite der Leiterkarte tradfri_dimmer_pcb_bot.jpg|Rückseite der Leiterkarte (gespiegelt) </gallery> Der Codename für das Leiterkärtchen ist allen Anschein nach "Nebula_1F". Ich bin kein Trekkie, aber ist das eine Anspielung auf eine Schiffsklasse? Halbwegs futuristisch ist die Bedienung immerhin… Hirn und Herz ist ein Silabs EFR32 MG1P132GI. Für ein Datenblatt sollte man den Suchbegriff auf "EFR32MG1" einschränken: "[https://www.silabs.com/products/wireless/mesh-networking/efr32mg-mighty-gecko-zigbee-thread-soc Mighty Gecko Mesh Networking Wireless SoCs for Zigbee and Thread]"-Produkt-Familie beim Hersteller. Leider hört es da auch schon fast auf. der IC rechts unten (mit der Aufschrift "I4BEB2 P10343") dürfte ein EEProm sein (nachdem der Gecko wohl keinen internen hat), bei den oberen beiden (Aufdruck "S2 636" und "628") dürfte es sich vermutlich um Magnetometer und Gyro handeln. Letzteres vermutlich eher links oben, da diese Komponenten meines Wissens etwas höhere Pulsstromaufnahmen (schließlich muss die Mikromechanik angeschubst werden) haben. Schön an den Geckos ist, dass man die Pins ziemlich komfortabel auf die gewünschten Funktionen routen kann, für’s Reverse Engineering ist das allerdings nicht so ganz schön. Wenn man die Leiterbahnen etwas verfolgt erkennt man, dass es die Leiterkarte mehr als 2 Lagen hat, halbwegs erstaunlich, bei der vergleichsweise geringen Komplexität. Bei der Leiterkartenproduktion wurde das aber wieder reingeholt: Die Leiterkarte ist gestanzt statt gefräst und das Material sieht eher billig als günstig aus. Immerhin sind die Kontakte vergoldet und es wurden einige Testpunkte spendiert – da wird sicher ein I²C dabei sein. ==Reverse Engineering== Mit ein bisschen Probing lässt sich der I²C der beiden ICs oben ermitteln. <gallery> tradfri_dimmer_rev_i2c.jpg|I²C des Dimmers </gallery> Sobald der Mikrocontroller mit Strom versorgt wird, wird auch fleißig kommuniziert - mit den Devices 0x19 und 0x6B (jeweils 7-Bit-Adressen). Die Initialisierung selbst gab zumindest mir keinen richtigen Aufschluss darüber, was das Bauteil auf Adresse 0x19 ist. Dreht man den Dimmer, sieht man allerdings recht schnell, wer auf 0x6B reagiert: <gallery> flat_cw_packet.png|Kommunikation mit dem Gyroskop </gallery> Wenig schreiben, viel Lesen - das muss ein Sensor sein. Mit ein wenig Scripting habe ich versucht, die Daten vom Logic auseinanderzupflücken (analyze_i2c.py und ein bisschen Excel). Ich habe noch nicht geprüft, ob das Script so funktioniert wie es beabsichtigt war, allerdings stehen die für die Drehung relevanten Daten in Register 0x3F: <gallery> tradfri_dimmer_rev_i22_flat_cw.png|Drehung in Uhrzeigersinn tradfri_dimmer_rev_i22_flat_ccw.png|Drehung gegen Uhrzeigersinn </gallery> Alle Aufzeichnungen (Init, Drehen in/gegen Uhrzeigersinn liegend und vertikal) zum Untersuchen und herumspielen gibt es natürlich zum [[Datei:tradfri_dimmer_rev_i2c_comm.zip|Herunterladen]] Dominik hat sich die Mühe gemacht und das Layout genauer analysiert: <gallery> tradfri_dimmer_pinout_erf32mg1.png|Pinout des µC (aus dem [https://www.silabs.com/documents/public/data-sheets/efr32mg1-datasheet.pdf Datenblatt]) tradfri_dimmer_rev_pinmap.jpg|Pin-Assignment auf der Leiterkarte (Bild von Dominik) </gallery> =Fernbedienung 303.388.49= [[Datei:tradfri_remote.jpg|thumb|Tradfri Fernbedienung]] ==Teardown== Habe ich noch nicht selbst durchgeführt, aber [https://www.heise.de/make/artikel/Ikea-Tradfri-Anleitung-fuer-ein-ESP8266-Lampen-Gateway-3598411.html Heise]. Dominik, der sich auch etwas näher mit dem Zerlegen und Umbauen der Fernbedienung auseinandergesetzt hat, gab folgende Tipps: * Das Gummi auf der Rückseite an zwei Stellen (45° versetzt/viertel Kreis) bis aufs Plastik drunter einschneiden (Teppichmesser) * Das Gummi abziehen (kleine Zange und wenn verfügbar ein bisschen Heißluft) * Dann schneide/reiße ich mich von der Batterie aus nach Außen (kleine Zange/Seitenschneider) * Ist erst einmal ein Schlitz da, ploppt der vordere Teil heraus (mit etwas biegen und drück) * Das mit dem Dremel war mir bis jetzt zu gefährlich, am Ende ist dann nur das PCB hin und der Dremel voller geschmolzenem Plastik ==Wandhalterung für Unterputz-Dosen== Dominik war es auch, der ein 3D-Design erstellt hat, mit dem man die Fernbedienung in die gleiche Form wie Jäger/Busch-Schalter zu bringen. Da er selbst keine Homepage/Blog hat, bat er mich, sein Design zur Verfügung zu stellen: <gallery> tradfri_remote_jaeger_render.png|Rendering der Frontplatte tradfri_remote_jaeger.jpg|Foto des Druckteils (Bild von Dominik) </gallery> Vielen Dank dafür! Da ich selbst unerfahren in Sachen 3D-Druck bin, kann ich die Daten leider nur as-is weitergeben. Alle Rechte bleiben bei Dominik (Kontakt kann ich in beidseitigem Einverständnis vermitteln). Unter Vorbehalt ist die kommerzielle Nutzung ausgeschlossen. [[Datei:tradfri_remote_frontplate.zip|Download]] =GU10-Lampe 803.652.70= ==Teardown== Zu dem Zeitpunkt, als ich die GU10-Lampe gekauft habe, war sie mit IIRC knapp 7 Euro diegünstigste verfügbare Lampe mit Funk. Mittlerweile (02/2019) hat sich der Preis mit 13 Euro fast verdoppelt. Ob sie anfangs unter Preis verkauft wurde, möchte ich nicht beschwören. Frisch as der Packung sieht sie wie folgt aus: <gallery> tradfri_gu10_back.jpg|von hinten tradfri_gu10_front.jpg|das "aktive" Ende </gallery> Der Deckel bzw. die Optik lässt sich mit einem flachen Schraubendreher erstaunlich leicht entfernen, innen ist das Teil auf ersten Blick eher unspektakulär: <gallery> tradfri_gu10_front_open.jpg|Entfernte Optik tradfri_gu10_heatsink.jpg|ohne LED-Leiterkarte </gallery> Ein herumflatterndes Kupferfähnchen? Sieht nach einem late fix zum Bestehen der EMV-Prüfungen aus. Das LED-Modul hat keine Wärmeleitpaste im Rücken und die leicht verklebte Metallplatte lässt sich mit sanfter Gewalt (mit dem Schraubendreher am Schraubloch hebeln) herausnehmen. Dahinter begrüßt einen die Elektronik – oder zumindest das Funkmodul. Es sieht besser aus als es ist. Ich bin mir nicht sicher, ob das Shielding seinen Namen verdient hat, es wackelt wie ein Kuhschwanz. Eine saubere elektromechanische Verbindung sieht auf jeden Fall anders aus. Ein bisschen mehr hebeln und das Innere erblickt das Tageslicht: <gallery> tradfri_gu10_module.jpg|Funkmodul mit Shielding und Fähnchen tradfri_gu10_module_open.jpg|...und entdeckelt </gallery> Das Silabs-Logo lässt sich erahnen, links unten sitzt auch ein "alter Bekannter". Bin mir ziemlich sicher, dass es sich hier um einen EEProm handelt. Im Bild sieht man auch, dass das Modul by design eher bescheiden eingelötet ist: unter der linken Kante sitzt ein SMD-Widerstand, unter der rechten nicht. Da man sowas maschinell nicht vernünftig gelötet bekommt: Mit ein bisschen Zug kommt auch das Netzteil + Controller raus. Es ist hinten nicht verlötet und sieht von oben zwar sehr eng gepackt aber dennoch halbwegs ok-ish aus: <gallery> tradfri_gu10_pcb_angle.jpg|Eng gepackter LED-Treiber </gallery> Von unten sollte man es – zumindest wenn man Elektroniker ist und einen schwachen Magen hat – besser nicht ansehen. Verdammt viele Handlötungen, mehr Lötzinn als mir lieb ist und noch mehr ekelhafte Flussmittelrückstände. Der 5-Beiner oben ist mit ZR7IB beschriftet (kein Datenblatt auffindbar). Das Bauteil im SO-8-Gehäuse heißt BEH7JB (auch nix zu finden). Die Qualität dieser Leiterkarte ist leider nicht wirklich rühmlich. Einen High-Pot-Test würde ich angesichts solcher Lötstellen nicht unbedingt machen: <gallery> tradfri_gu10_pcb_bot.jpg|LED-Treiber von unten tradfri_gu10_pcb_nohipot.jpg|Lötqualität des Treibers </gallery> ==Reverse Engineering== Die Beschaltung des Funkmoduls kann man anhand der Leiterkarte relativ einfach ermitteln: <gallery> tradfri_gu10_rf_module.jpg|Tradfri RF-Modul </gallery> Von in dieser Ansicht unten von links nach rechts: {| class="wikitable" ! Pin || Funktion |- | 1 || unbekannt |- | 1 || unbekannt |- | 1 || unbekannt |- | 1 || PWM Out |- | 1 || GND |- | 1 || 3,3 V |} Jemand anderes hat eine genauere Untersuchung durchgeführt und [https://tradfri.blogspot.com/2017/04/pinout-of-tradfri-zigbee-module.html alle Pins gemappt]. Was kommt raus? An den Logic Analyzer angeklemmt zeigt sich bei niedrigster Helligkeit eine On-Time von 94,92 µs und eine Frequenz von genau 600 Hz. Der Duty-Cycle ist also bei 5,695 %. Den Slider in der App auf etwa die Hälfte gezogen ergibt sich ein Duty-Cycle von ca. 24 %, bei dreiviertel sind es 50 % Duty-Cycle. Die Frequenz bleibt konstant. An dieser Stelle endet meine Untersuchung. Der Github-User [https://github.com/basilfx/TRADFRI-Hacking basilfx] ist da deutlich tiefer in Sachen Hacking eingestiegen. [[Kategorie:Automatisierung, Beleuchtung]] f1e8015eca09a5d6f2bfc37ccbb685cf7a28423e 1291 1288 2019-02-17T19:20:01Z Chris 2 /* Reverse Engineering */ wikitext text/x-wiki Trådfri, wie es aussieht kein richtiges [https://sv.wiktionary.org/wiki/Tr%C3%A5dfri schwedisches Wort], das für das drahtlose Beleuchtungssystem von Ikea steht. Da ich mittlerweile ein paar Lampen aus dem Möbelhaus bei mir im Einsatz habe, wollte ich mich ein wenig damit auseinandersetzen Anmerkung: Einige Teile des Artikels sind aus dem [//hobbyelektronik.org/b/2018/05/teardown-von-tradfri/ Blog übernommen] =Kabelloser Dimmer 003.478.31= [[Datei:tradfri_dimmer.jpg|thumb|Tradfri Dimmer, nahezu unsichtbar auf weißem Grund]] ==Teardown== Nimmt man das "User-servicable" Gehäuse vom Dimmer ab, bekommt man folgendes zu Gesicht: <gallery> tradfri_dimmer_assy_back2.jpg|Dimmer, innen von hinten tradfri_dimmer_assy_front.jpg|Dimmer, innen von vorne </gallery> Die Typenbezeichnung ist also neben der Ikea-Nummer ICTC-G-1. Obwohl das Gehäuse den Anschein macht, als wäre es Ultraschall-verschweißt, ist es nur geklipst. "Built to a price", das Schweißen wäre ein zusätzlicher Produktionsschritt und die Spritzguss muss sowieso ran. Mit einem vorsichtig angesetztem Schraubendreher lassen sich die Gehäuseteile trennen und die Leiterkarte kommt zum Vorschein: <gallery> tradfri_dimmer_pcb_assy.jpg|Leiterkarte mit Batteriehalter tradfri_dimmer_assy_back.jpg|Mech. Batteriehalter und Taster </gallery> Das Rückteil ist weniger spektakulär – ein Magnet und eine Kontaktfeder für die Batterie. In der anderen Hälfte steckt die "Magie": <gallery> tradfri_dimmer_pcb_top.jpg|Bestückungsseite der Leiterkarte tradfri_dimmer_pcb_bot.jpg|Rückseite der Leiterkarte (gespiegelt) </gallery> Der Codename für das Leiterkärtchen ist allen Anschein nach "Nebula_1F". Ich bin kein Trekkie, aber ist das eine Anspielung auf eine Schiffsklasse? Halbwegs futuristisch ist die Bedienung immerhin… Hirn und Herz ist ein Silabs EFR32 MG1P132GI. Für ein Datenblatt sollte man den Suchbegriff auf "EFR32MG1" einschränken: "[https://www.silabs.com/products/wireless/mesh-networking/efr32mg-mighty-gecko-zigbee-thread-soc Mighty Gecko Mesh Networking Wireless SoCs for Zigbee and Thread]"-Produkt-Familie beim Hersteller. Leider hört es da auch schon fast auf. der IC rechts unten (mit der Aufschrift "I4BEB2 P10343") dürfte ein EEProm sein (nachdem der Gecko wohl keinen internen hat), bei den oberen beiden (Aufdruck "S2 636" und "628") dürfte es sich vermutlich um Magnetometer und Gyro handeln. Letzteres vermutlich eher links oben, da diese Komponenten meines Wissens etwas höhere Pulsstromaufnahmen (schließlich muss die Mikromechanik angeschubst werden) haben. Schön an den Geckos ist, dass man die Pins ziemlich komfortabel auf die gewünschten Funktionen routen kann, für’s Reverse Engineering ist das allerdings nicht so ganz schön. Wenn man die Leiterbahnen etwas verfolgt erkennt man, dass es die Leiterkarte mehr als 2 Lagen hat, halbwegs erstaunlich, bei der vergleichsweise geringen Komplexität. Bei der Leiterkartenproduktion wurde das aber wieder reingeholt: Die Leiterkarte ist gestanzt statt gefräst und das Material sieht eher billig als günstig aus. Immerhin sind die Kontakte vergoldet und es wurden einige Testpunkte spendiert – da wird sicher ein I²C dabei sein. ==Reverse Engineering== Mit ein bisschen Probing lässt sich der I²C der beiden ICs oben ermitteln. <gallery> tradfri_dimmer_rev_i2c.jpg|I²C des Dimmers </gallery> Sobald der Mikrocontroller mit Strom versorgt wird, wird auch fleißig kommuniziert - mit den Devices 0x19 und 0x6B (jeweils 7-Bit-Adressen). Die Initialisierung selbst gab zumindest mir keinen richtigen Aufschluss darüber, was das Bauteil auf Adresse 0x19 ist. Dreht man den Dimmer, sieht man allerdings recht schnell, wer auf 0x6B reagiert: <gallery> flat_cw_packet.png|Kommunikation mit dem Gyroskop </gallery> Wenig schreiben, viel Lesen - das muss ein Sensor sein. Mit ein wenig Scripting habe ich versucht, die Daten vom Logic auseinanderzupflücken (analyze_i2c.py und ein bisschen Excel). Ich habe noch nicht geprüft, ob das Script so funktioniert wie es beabsichtigt war, allerdings stehen die für die Drehung relevanten Daten in Register 0x3F: <gallery> tradfri_dimmer_rev_i22_flat_cw.png|Drehung in Uhrzeigersinn tradfri_dimmer_rev_i22_flat_ccw.png|Drehung gegen Uhrzeigersinn </gallery> Alle Aufzeichnungen (Init, Drehen in/gegen Uhrzeigersinn liegend und vertikal) zum Untersuchen und herumspielen gibt es natürlich zum herunterladen: [[Datei:tradfri_dimmer_rev_i2c_comm.zip]] Dominik hat sich die Mühe gemacht und das Layout genauer analysiert: <gallery> tradfri_dimmer_pinout_erf32mg1.png|Pinout des µC (aus dem [https://www.silabs.com/documents/public/data-sheets/efr32mg1-datasheet.pdf Datenblatt]) tradfri_dimmer_rev_pinmap.jpg|Pin-Assignment auf der Leiterkarte (Bild von Dominik) </gallery> [[Kategorie:Hausautomatisierung]] [[Kategorie:Beleuchtung]] =Fernbedienung 303.388.49= [[Datei:tradfri_remote.jpg|thumb|Tradfri Fernbedienung]] ==Teardown== Habe ich noch nicht selbst durchgeführt, aber [https://www.heise.de/make/artikel/Ikea-Tradfri-Anleitung-fuer-ein-ESP8266-Lampen-Gateway-3598411.html Heise]. Dominik, der sich auch etwas näher mit dem Zerlegen und Umbauen der Fernbedienung auseinandergesetzt hat, gab folgende Tipps: * Das Gummi auf der Rückseite an zwei Stellen (45° versetzt/viertel Kreis) bis aufs Plastik drunter einschneiden (Teppichmesser) * Das Gummi abziehen (kleine Zange und wenn verfügbar ein bisschen Heißluft) * Dann schneide/reiße ich mich von der Batterie aus nach Außen (kleine Zange/Seitenschneider) * Ist erst einmal ein Schlitz da, ploppt der vordere Teil heraus (mit etwas biegen und drück) * Das mit dem Dremel war mir bis jetzt zu gefährlich, am Ende ist dann nur das PCB hin und der Dremel voller geschmolzenem Plastik ==Wandhalterung für Unterputz-Dosen== Dominik war es auch, der ein 3D-Design erstellt hat, mit dem man die Fernbedienung in die gleiche Form wie Jäger/Busch-Schalter zu bringen. Da er selbst keine Homepage/Blog hat, bat er mich, sein Design zur Verfügung zu stellen: <gallery> tradfri_remote_jaeger_render.png|Rendering der Frontplatte tradfri_remote_jaeger.jpg|Foto des Druckteils (Bild von Dominik) </gallery> Vielen Dank dafür! Da ich selbst unerfahren in Sachen 3D-Druck bin, kann ich die Daten leider nur as-is weitergeben. Alle Rechte bleiben bei Dominik (Kontakt kann ich in beidseitigem Einverständnis vermitteln). Unter Vorbehalt ist die kommerzielle Nutzung ausgeschlossen. [[Datei:tradfri_remote_frontplate.zip|Download]] =GU10-Lampe 803.652.70= ==Teardown== Zu dem Zeitpunkt, als ich die GU10-Lampe gekauft habe, war sie mit IIRC knapp 7 Euro diegünstigste verfügbare Lampe mit Funk. Mittlerweile (02/2019) hat sich der Preis mit 13 Euro fast verdoppelt. Ob sie anfangs unter Preis verkauft wurde, möchte ich nicht beschwören. Frisch as der Packung sieht sie wie folgt aus: <gallery> tradfri_gu10_back.jpg|von hinten tradfri_gu10_front.jpg|das "aktive" Ende </gallery> Der Deckel bzw. die Optik lässt sich mit einem flachen Schraubendreher erstaunlich leicht entfernen, innen ist das Teil auf ersten Blick eher unspektakulär: <gallery> tradfri_gu10_front_open.jpg|Entfernte Optik tradfri_gu10_heatsink.jpg|ohne LED-Leiterkarte </gallery> Ein herumflatterndes Kupferfähnchen? Sieht nach einem late fix zum Bestehen der EMV-Prüfungen aus. Das LED-Modul hat keine Wärmeleitpaste im Rücken und die leicht verklebte Metallplatte lässt sich mit sanfter Gewalt (mit dem Schraubendreher am Schraubloch hebeln) herausnehmen. Dahinter begrüßt einen die Elektronik – oder zumindest das Funkmodul. Es sieht besser aus als es ist. Ich bin mir nicht sicher, ob das Shielding seinen Namen verdient hat, es wackelt wie ein Kuhschwanz. Eine saubere elektromechanische Verbindung sieht auf jeden Fall anders aus. Ein bisschen mehr hebeln und das Innere erblickt das Tageslicht: <gallery> tradfri_gu10_module.jpg|Funkmodul mit Shielding und Fähnchen tradfri_gu10_module_open.jpg|...und entdeckelt </gallery> Das Silabs-Logo lässt sich erahnen, links unten sitzt auch ein "alter Bekannter". Bin mir ziemlich sicher, dass es sich hier um einen EEProm handelt. Im Bild sieht man auch, dass das Modul by design eher bescheiden eingelötet ist: unter der linken Kante sitzt ein SMD-Widerstand, unter der rechten nicht. Da man sowas maschinell nicht vernünftig gelötet bekommt: Mit ein bisschen Zug kommt auch das Netzteil + Controller raus. Es ist hinten nicht verlötet und sieht von oben zwar sehr eng gepackt aber dennoch halbwegs ok-ish aus: <gallery> tradfri_gu10_pcb_angle.jpg|Eng gepackter LED-Treiber </gallery> Von unten sollte man es – zumindest wenn man Elektroniker ist und einen schwachen Magen hat – besser nicht ansehen. Verdammt viele Handlötungen, mehr Lötzinn als mir lieb ist und noch mehr ekelhafte Flussmittelrückstände. Der 5-Beiner oben ist mit ZR7IB beschriftet (kein Datenblatt auffindbar). Das Bauteil im SO-8-Gehäuse heißt BEH7JB (auch nix zu finden). Die Qualität dieser Leiterkarte ist leider nicht wirklich rühmlich. Einen High-Pot-Test würde ich angesichts solcher Lötstellen nicht unbedingt machen: <gallery> tradfri_gu10_pcb_bot.jpg|LED-Treiber von unten tradfri_gu10_pcb_nohipot.jpg|Lötqualität des Treibers </gallery> ==Reverse Engineering== Die Beschaltung des Funkmoduls kann man anhand der Leiterkarte relativ einfach ermitteln: <gallery> tradfri_gu10_rf_module.jpg|Tradfri RF-Modul </gallery> Von in dieser Ansicht unten von links nach rechts: {| class="wikitable" ! Pin || Funktion |- | 1 || unbekannt |- | 1 || unbekannt |- | 1 || unbekannt |- | 1 || PWM Out |- | 1 || GND |- | 1 || 3,3 V |} Jemand anderes hat eine genauere Untersuchung durchgeführt und [https://tradfri.blogspot.com/2017/04/pinout-of-tradfri-zigbee-module.html alle Pins gemappt]. Was kommt raus? An den Logic Analyzer angeklemmt zeigt sich bei niedrigster Helligkeit eine On-Time von 94,92 µs und eine Frequenz von genau 600 Hz. Der Duty-Cycle ist also bei 5,695 %. Den Slider in der App auf etwa die Hälfte gezogen ergibt sich ein Duty-Cycle von ca. 24 %, bei dreiviertel sind es 50 % Duty-Cycle. Die Frequenz bleibt konstant. An dieser Stelle endet meine Untersuchung. Der Github-User [https://github.com/basilfx/TRADFRI-Hacking basilfx] ist da deutlich tiefer in Sachen Hacking eingestiegen. [[Kategorie:Automatisierung, Beleuchtung]] 801b618124efa5e14cf940a0bcf6ce0d307cd947 1292 1291 2019-02-17T19:20:19Z Chris 2 wikitext text/x-wiki Trådfri, wie es aussieht kein richtiges [https://sv.wiktionary.org/wiki/Tr%C3%A5dfri schwedisches Wort], das für das drahtlose Beleuchtungssystem von Ikea steht. Da ich mittlerweile ein paar Lampen aus dem Möbelhaus bei mir im Einsatz habe, wollte ich mich ein wenig damit auseinandersetzen Anmerkung: Einige Teile des Artikels sind aus dem [//hobbyelektronik.org/b/2018/05/teardown-von-tradfri/ Blog übernommen] =Kabelloser Dimmer 003.478.31= [[Datei:tradfri_dimmer.jpg|thumb|Tradfri Dimmer, nahezu unsichtbar auf weißem Grund]] ==Teardown== Nimmt man das "User-servicable" Gehäuse vom Dimmer ab, bekommt man folgendes zu Gesicht: <gallery> tradfri_dimmer_assy_back2.jpg|Dimmer, innen von hinten tradfri_dimmer_assy_front.jpg|Dimmer, innen von vorne </gallery> Die Typenbezeichnung ist also neben der Ikea-Nummer ICTC-G-1. Obwohl das Gehäuse den Anschein macht, als wäre es Ultraschall-verschweißt, ist es nur geklipst. "Built to a price", das Schweißen wäre ein zusätzlicher Produktionsschritt und die Spritzguss muss sowieso ran. Mit einem vorsichtig angesetztem Schraubendreher lassen sich die Gehäuseteile trennen und die Leiterkarte kommt zum Vorschein: <gallery> tradfri_dimmer_pcb_assy.jpg|Leiterkarte mit Batteriehalter tradfri_dimmer_assy_back.jpg|Mech. Batteriehalter und Taster </gallery> Das Rückteil ist weniger spektakulär – ein Magnet und eine Kontaktfeder für die Batterie. In der anderen Hälfte steckt die "Magie": <gallery> tradfri_dimmer_pcb_top.jpg|Bestückungsseite der Leiterkarte tradfri_dimmer_pcb_bot.jpg|Rückseite der Leiterkarte (gespiegelt) </gallery> Der Codename für das Leiterkärtchen ist allen Anschein nach "Nebula_1F". Ich bin kein Trekkie, aber ist das eine Anspielung auf eine Schiffsklasse? Halbwegs futuristisch ist die Bedienung immerhin… Hirn und Herz ist ein Silabs EFR32 MG1P132GI. Für ein Datenblatt sollte man den Suchbegriff auf "EFR32MG1" einschränken: "[https://www.silabs.com/products/wireless/mesh-networking/efr32mg-mighty-gecko-zigbee-thread-soc Mighty Gecko Mesh Networking Wireless SoCs for Zigbee and Thread]"-Produkt-Familie beim Hersteller. Leider hört es da auch schon fast auf. der IC rechts unten (mit der Aufschrift "I4BEB2 P10343") dürfte ein EEProm sein (nachdem der Gecko wohl keinen internen hat), bei den oberen beiden (Aufdruck "S2 636" und "628") dürfte es sich vermutlich um Magnetometer und Gyro handeln. Letzteres vermutlich eher links oben, da diese Komponenten meines Wissens etwas höhere Pulsstromaufnahmen (schließlich muss die Mikromechanik angeschubst werden) haben. Schön an den Geckos ist, dass man die Pins ziemlich komfortabel auf die gewünschten Funktionen routen kann, für’s Reverse Engineering ist das allerdings nicht so ganz schön. Wenn man die Leiterbahnen etwas verfolgt erkennt man, dass es die Leiterkarte mehr als 2 Lagen hat, halbwegs erstaunlich, bei der vergleichsweise geringen Komplexität. Bei der Leiterkartenproduktion wurde das aber wieder reingeholt: Die Leiterkarte ist gestanzt statt gefräst und das Material sieht eher billig als günstig aus. Immerhin sind die Kontakte vergoldet und es wurden einige Testpunkte spendiert – da wird sicher ein I²C dabei sein. ==Reverse Engineering== Mit ein bisschen Probing lässt sich der I²C der beiden ICs oben ermitteln. <gallery> tradfri_dimmer_rev_i2c.jpg|I²C des Dimmers </gallery> Sobald der Mikrocontroller mit Strom versorgt wird, wird auch fleißig kommuniziert - mit den Devices 0x19 und 0x6B (jeweils 7-Bit-Adressen). Die Initialisierung selbst gab zumindest mir keinen richtigen Aufschluss darüber, was das Bauteil auf Adresse 0x19 ist. Dreht man den Dimmer, sieht man allerdings recht schnell, wer auf 0x6B reagiert: <gallery> flat_cw_packet.png|Kommunikation mit dem Gyroskop </gallery> Wenig schreiben, viel Lesen - das muss ein Sensor sein. Mit ein wenig Scripting habe ich versucht, die Daten vom Logic auseinanderzupflücken (analyze_i2c.py und ein bisschen Excel). Ich habe noch nicht geprüft, ob das Script so funktioniert wie es beabsichtigt war, allerdings stehen die für die Drehung relevanten Daten in Register 0x3F: <gallery> tradfri_dimmer_rev_i22_flat_cw.png|Drehung in Uhrzeigersinn tradfri_dimmer_rev_i22_flat_ccw.png|Drehung gegen Uhrzeigersinn </gallery> Alle Aufzeichnungen (Init, Drehen in/gegen Uhrzeigersinn liegend und vertikal) zum Untersuchen und herumspielen gibt es natürlich zum herunterladen: [[Datei:tradfri_dimmer_rev_i2c_comm.zip]] Dominik hat sich die Mühe gemacht und das Layout genauer analysiert: <gallery> tradfri_dimmer_pinout_erf32mg1.png|Pinout des µC (aus dem [https://www.silabs.com/documents/public/data-sheets/efr32mg1-datasheet.pdf Datenblatt]) tradfri_dimmer_rev_pinmap.jpg|Pin-Assignment auf der Leiterkarte (Bild von Dominik) </gallery> =Fernbedienung 303.388.49= [[Datei:tradfri_remote.jpg|thumb|Tradfri Fernbedienung]] ==Teardown== Habe ich noch nicht selbst durchgeführt, aber [https://www.heise.de/make/artikel/Ikea-Tradfri-Anleitung-fuer-ein-ESP8266-Lampen-Gateway-3598411.html Heise]. Dominik, der sich auch etwas näher mit dem Zerlegen und Umbauen der Fernbedienung auseinandergesetzt hat, gab folgende Tipps: * Das Gummi auf der Rückseite an zwei Stellen (45° versetzt/viertel Kreis) bis aufs Plastik drunter einschneiden (Teppichmesser) * Das Gummi abziehen (kleine Zange und wenn verfügbar ein bisschen Heißluft) * Dann schneide/reiße ich mich von der Batterie aus nach Außen (kleine Zange/Seitenschneider) * Ist erst einmal ein Schlitz da, ploppt der vordere Teil heraus (mit etwas biegen und drück) * Das mit dem Dremel war mir bis jetzt zu gefährlich, am Ende ist dann nur das PCB hin und der Dremel voller geschmolzenem Plastik ==Wandhalterung für Unterputz-Dosen== Dominik war es auch, der ein 3D-Design erstellt hat, mit dem man die Fernbedienung in die gleiche Form wie Jäger/Busch-Schalter zu bringen. Da er selbst keine Homepage/Blog hat, bat er mich, sein Design zur Verfügung zu stellen: <gallery> tradfri_remote_jaeger_render.png|Rendering der Frontplatte tradfri_remote_jaeger.jpg|Foto des Druckteils (Bild von Dominik) </gallery> Vielen Dank dafür! Da ich selbst unerfahren in Sachen 3D-Druck bin, kann ich die Daten leider nur as-is weitergeben. Alle Rechte bleiben bei Dominik (Kontakt kann ich in beidseitigem Einverständnis vermitteln). Unter Vorbehalt ist die kommerzielle Nutzung ausgeschlossen. [[Datei:tradfri_remote_frontplate.zip|Download]] =GU10-Lampe 803.652.70= ==Teardown== Zu dem Zeitpunkt, als ich die GU10-Lampe gekauft habe, war sie mit IIRC knapp 7 Euro diegünstigste verfügbare Lampe mit Funk. Mittlerweile (02/2019) hat sich der Preis mit 13 Euro fast verdoppelt. Ob sie anfangs unter Preis verkauft wurde, möchte ich nicht beschwören. Frisch as der Packung sieht sie wie folgt aus: <gallery> tradfri_gu10_back.jpg|von hinten tradfri_gu10_front.jpg|das "aktive" Ende </gallery> Der Deckel bzw. die Optik lässt sich mit einem flachen Schraubendreher erstaunlich leicht entfernen, innen ist das Teil auf ersten Blick eher unspektakulär: <gallery> tradfri_gu10_front_open.jpg|Entfernte Optik tradfri_gu10_heatsink.jpg|ohne LED-Leiterkarte </gallery> Ein herumflatterndes Kupferfähnchen? Sieht nach einem late fix zum Bestehen der EMV-Prüfungen aus. Das LED-Modul hat keine Wärmeleitpaste im Rücken und die leicht verklebte Metallplatte lässt sich mit sanfter Gewalt (mit dem Schraubendreher am Schraubloch hebeln) herausnehmen. Dahinter begrüßt einen die Elektronik – oder zumindest das Funkmodul. Es sieht besser aus als es ist. Ich bin mir nicht sicher, ob das Shielding seinen Namen verdient hat, es wackelt wie ein Kuhschwanz. Eine saubere elektromechanische Verbindung sieht auf jeden Fall anders aus. Ein bisschen mehr hebeln und das Innere erblickt das Tageslicht: <gallery> tradfri_gu10_module.jpg|Funkmodul mit Shielding und Fähnchen tradfri_gu10_module_open.jpg|...und entdeckelt </gallery> Das Silabs-Logo lässt sich erahnen, links unten sitzt auch ein "alter Bekannter". Bin mir ziemlich sicher, dass es sich hier um einen EEProm handelt. Im Bild sieht man auch, dass das Modul by design eher bescheiden eingelötet ist: unter der linken Kante sitzt ein SMD-Widerstand, unter der rechten nicht. Da man sowas maschinell nicht vernünftig gelötet bekommt: Mit ein bisschen Zug kommt auch das Netzteil + Controller raus. Es ist hinten nicht verlötet und sieht von oben zwar sehr eng gepackt aber dennoch halbwegs ok-ish aus: <gallery> tradfri_gu10_pcb_angle.jpg|Eng gepackter LED-Treiber </gallery> Von unten sollte man es – zumindest wenn man Elektroniker ist und einen schwachen Magen hat – besser nicht ansehen. Verdammt viele Handlötungen, mehr Lötzinn als mir lieb ist und noch mehr ekelhafte Flussmittelrückstände. Der 5-Beiner oben ist mit ZR7IB beschriftet (kein Datenblatt auffindbar). Das Bauteil im SO-8-Gehäuse heißt BEH7JB (auch nix zu finden). Die Qualität dieser Leiterkarte ist leider nicht wirklich rühmlich. Einen High-Pot-Test würde ich angesichts solcher Lötstellen nicht unbedingt machen: <gallery> tradfri_gu10_pcb_bot.jpg|LED-Treiber von unten tradfri_gu10_pcb_nohipot.jpg|Lötqualität des Treibers </gallery> ==Reverse Engineering== Die Beschaltung des Funkmoduls kann man anhand der Leiterkarte relativ einfach ermitteln: <gallery> tradfri_gu10_rf_module.jpg|Tradfri RF-Modul </gallery> Von in dieser Ansicht unten von links nach rechts: {| class="wikitable" ! Pin || Funktion |- | 1 || unbekannt |- | 1 || unbekannt |- | 1 || unbekannt |- | 1 || PWM Out |- | 1 || GND |- | 1 || 3,3 V |} Jemand anderes hat eine genauere Untersuchung durchgeführt und [https://tradfri.blogspot.com/2017/04/pinout-of-tradfri-zigbee-module.html alle Pins gemappt]. Was kommt raus? An den Logic Analyzer angeklemmt zeigt sich bei niedrigster Helligkeit eine On-Time von 94,92 µs und eine Frequenz von genau 600 Hz. Der Duty-Cycle ist also bei 5,695 %. Den Slider in der App auf etwa die Hälfte gezogen ergibt sich ein Duty-Cycle von ca. 24 %, bei dreiviertel sind es 50 % Duty-Cycle. Die Frequenz bleibt konstant. An dieser Stelle endet meine Untersuchung. Der Github-User [https://github.com/basilfx/TRADFRI-Hacking basilfx] ist da deutlich tiefer in Sachen Hacking eingestiegen. [[Kategorie:Hausautomatisierung]] [[Kategorie:Beleuchtung]] be99e80175a8b6ce979c4560abf05e22e3aba242 Datei:Tradfri dimmer pcb top.jpg 6 567 1289 2019-02-17T19:14:47Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri dimmer pcb bot.jpg 6 568 1290 2019-02-17T19:16:41Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Tradfri gu10 module.jpg 6 569 1293 2019-02-17T19:31:00Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder 0 120 1296 1295 2019-02-24T15:05:08Z Chris 2 /* FAQ */ Es sollte eine Frage sein. wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==FAQ== * Ist der Adapter mit allen Resol- bzw. Viessmann-Anlagen kompatibel? Vermutlich nein. Manche Resol-Anlagen verwenden wohl RS-485. Ein Indiz für die Kompatibilität ist die Angabe in der Anleitung, dass die Schnittstelle Strom zur Verfügung stellt. * Kann der Adapter direkt an einem Single-Board-Computer (z. B. Raspberry Pi) verwendet werden? Ja. Bisher wurde die Schaltung mit 3,3 und 5 V auf der Sekundärseite getestet. Für 1,8 V I/O-Spannung kann ich noch keine Aussage machen. * Gibt es Software für Single-Board-Computer oder den PC? Nein, noch nicht. Aber es steht auf der (langen) TODO-Liste. * Kann der Adapter direkt am PC betrieben werden? Es kommt darauf an. Sowohl für USB als auch RS-232 (klassischer COM-Port) wird ein Adapter benötigt. Für USB tut es ein USB-UART-Adapter (die man z. B. zum Bespielen von Arduinos kennt, Beispiel FT232), für RS-232 muss ein Pegelwandler (z. B. MAX2232) zwischengeschaltet werden. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] a769d10831d839cd9c4662cbc27a2465f348d909 1297 1296 2019-02-24T15:06:57Z Chris 2 oh, es gibt ja schon FAQ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat, diesem aber nicht entspricht. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 67a6485860b7802d7fe123bf096447bc6cba5ec1 1339 1297 2019-05-05T13:07:33Z Chris 2 /* Hardwareschnittstelle */ verwirrenden Satz korrigiert wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] d03073f49229b257329d3f524b40acf1f1bd3ea3 VBus-Decoder/FAQ 0 196 1298 557 2019-02-24T15:08:21Z Chris 2 wikitext text/x-wiki =Allgemein= *Ich habe eine Solaranlage von der Firma XYZ - kann ich sie mit deiner Schaltung/Software auslesen? Jein. Es kommt darauf an, welche Hardwareschnittstelle und welches Protokoll die Anlage verwendet. Steht Resol drauf, ist die Wahrscheinlichkeit hoch. Auch scheinen (neben meinem Regler) ein paar andere Regler von Viessman die gleiche Schnittstelle zu haben. Ich habe allerdings keinerlei Informationen, welcher Hersteller welche Schnittstelle welches Protokoll verwendet. Leider ;) =VBus-Adapter Nano= * Ist der Adapter mit allen Resol- bzw. Viessmann-Anlagen kompatibel? Vermutlich nein. Manche Resol-Anlagen verwenden wohl RS-485. Ein Indiz für die Kompatibilität ist die Angabe in der Anleitung, dass die Schnittstelle Strom zur Verfügung stellt. * Kann der Adapter direkt an einem Single-Board-Computer (z. B. Raspberry Pi) verwendet werden? Ja. Bisher wurde die Schaltung mit 3,3 und 5 V auf der Sekundärseite getestet. Für 1,8 V I/O-Spannung kann ich noch keine Aussage machen. * Gibt es Software für Single-Board-Computer oder den PC? Nein, noch nicht. Aber es steht auf der (langen) TODO-Liste. * Kann der Adapter direkt am PC betrieben werden? Es kommt darauf an. Sowohl für USB als auch RS-232 (klassischer COM-Port) wird ein Adapter benötigt. Für USB tut es ein USB-UART-Adapter (die man z. B. zum Bespielen von Arduinos kennt, Beispiel FT232), für RS-232 muss ein Pegelwandler (z. B. MAX2232) zwischengeschaltet werden. 1f1ef754f43bfd48173d29f382b98395413036eb 1299 1298 2019-02-24T16:30:46Z Chris 2 /* VBus-Adapter Nano */ Links auf Fremdprojekte wikitext text/x-wiki =Allgemein= *Ich habe eine Solaranlage von der Firma XYZ - kann ich sie mit deiner Schaltung/Software auslesen? Jein. Es kommt darauf an, welche Hardwareschnittstelle und welches Protokoll die Anlage verwendet. Steht Resol drauf, ist die Wahrscheinlichkeit hoch. Auch scheinen (neben meinem Regler) ein paar andere Regler von Viessman die gleiche Schnittstelle zu haben. Ich habe allerdings keinerlei Informationen, welcher Hersteller welche Schnittstelle welches Protokoll verwendet. Leider ;) =VBus-Adapter Nano= * Ist der Adapter mit allen Resol- bzw. Viessmann-Anlagen kompatibel? Vermutlich nein. Manche Resol-Anlagen verwenden wohl RS-485. Ein Indiz für die Kompatibilität ist die Angabe in der Anleitung, dass die Schnittstelle Strom zur Verfügung stellt. * Kann der Adapter direkt an einem Single-Board-Computer (z. B. Raspberry Pi) verwendet werden? Ja. Bisher wurde die Schaltung mit 3,3 und 5 V auf der Sekundärseite getestet. Für 1,8 V I/O-Spannung kann ich noch keine Aussage machen. * Gibt es Software für Single-Board-Computer oder den PC? Nein, noch nicht. Aber es steht auf der (langen) TODO-Liste. Daniel Wippermann hat auf seinem [https://github.com/danielwippermann/ Github-Account] einige Sourcen, auch von [https://github.com/martinvw/vbusdecode martinvw] gibt es etwas dort. Habe bis jetzt keines von beiden Projekten selbst getestet. * Kann der Adapter direkt am PC betrieben werden? Es kommt darauf an. Sowohl für USB als auch RS-232 (klassischer COM-Port) wird ein Adapter benötigt. Für USB tut es ein USB-UART-Adapter (die man z. B. zum Bespielen von Arduinos kennt, Beispiel FT232), für RS-232 muss ein Pegelwandler (z. B. MAX2232) zwischengeschaltet werden. b84567c5a4131b66ba088935f5104bb1359aa75e Energieerfassung 0 168 1300 1053 2019-03-14T19:56:37Z Chris 2 Link korrigiert. wikitext text/x-wiki '''Achtung: Dieser Artikel und das Projekt dahinter ist noch lange nicht fertig. Es kann sich also sowohl an dieser Dokumentation als auch am Projekt selbst noch einiges ändern.''' Seit 2005 steht eine Grundwasserwärmepumpe zum Heizen von Brauchwasser und Räumen im Keller. Im Sommer danach kam eine Solaranlage dazu. Dadurch heizen wir vollständig mit regenerativen Energiequellen. Zugegebermaßen: nicht ganz. Der Strom für die Wärmepumpe stammt vermutlich hauptsächlich aus nicht-regenerativen Quellen. Da vor allem bei der Solaranlage der Energieertrag bzw. die Heizleistung nicht sonderlich gut eingeschätzt werden kann, habe ich mir das Ziel gesetzt, das Verhalten der Anlage(n) etwas und, wie bereits in [[What's next?]] erwähnt, den Energieverbrauch bei uns im Haus etwas unter die Lupe zu nehmen. =Eckdaten= Das Herzstück der Angelegenheit wird ein leicht aufgewerteter AVR-Net-IO von Pollin. Dieser soll die Daten erfassen und zunächst live ins Netzwerk stellen. Später soll er die gesammelten Daten alle paar Stunden per HTTP-Get, -Post oder auch per E-Mail an meinen Webserver schicken, der sie in eine relationale Datenbank speichert und für den User aufbereitet. Erfasst werden soll: * Stromverbrauch des Haushalts * Stromverbrauch der Wärmepumpe (2 Tarife) * Freigabe- und Betriebszeiten der Wärmepumpe * Wasserverbrauch * Kesseltemperatur Brauchwasser (wie oft stand ich bibbernd in der Dusche) * Kenndaten der Solaranlage * Was sich sonst so ergibt =Datenerfassung= ==Stromzähler== [[Datei:Nrg hauptzaehler.jpg|thumb|Stromzähler mit aufgesetzter Erfassungseinheit]] Zwar wurde hier kürzlich der Stromzähler gewechselt, leider ist es immer noch ein schnöder ohne Taktausgang oder blinkenden LED. Das Ding, oder besser: die Dinger müssen also auf die altmodische Weise erfasst werden: Die [[:wpde:Ferraris-Zähler|Ferraris-Scheibe]] bzw. deren Markierung wird optisch gelesen. Damit ich nicht die ganze Zeit im Keller stehen muss, habe ich mir für den Schaltungsentwurf einen Wechselstromzähler ausgeliehen. Leider zeigte sich dieser von kleineren Verbrauchern gänzlich unbeeindruckt, die Scheibe bewegte sich keinen Millimeter. Da ich zum Entwickeln der Messschaltung nicht immer Kaffee oder Wasser kochen wollte, wurde die Scheibe auf eine etwas unethische bewegt: ein kleiner Elektromotor sorgt für die nötige Rotation. Das war zwar laut wie die Hölle und hörte sich nach übelster Dorfdisco an, ließ den roten Strich dafür im Sekundentakt vorbeiflitzen. Aufgrund des hohen Kontrasts des Strichs zur restlichen Scheibe wählte ich 'superhelle' grüne LEDs, die mit dem Standard-Fototransistor BPW40 erfasst werden soll. Prinzipiell keine schlechte Idee, doch die Fototranse ist auf das gelb-grün doch unempfindlicher als erwartet und das 'superhell' entpuppte sich ziemlich schnell als super Reinfall. Zum Glück lagen noch ein paar halbwegs helle IR-LEDs herum, die auch noch mit 1k-Vorwiderstand fast Löcher in die Kamera meines Handys brennen. Der Kontrast ist trotz der ähnlichen "Farbe" erstaulich gut. Liegt wohl hauptsächlich daran, dass die rote Markierung deutlich matter als der Rest der Scheibe ist. Bleibt noch die Frage, wie man die Ausleseeinheit am Zähler befestigt. Ein Holzrahmen wie bei [http://www.zabex.de/site/gaswasserstrom.html Zabex‘ Lösung] scheidet aus. Erstens unpraktisch zu bauen und anzubringen, zweitens inkompatibel zu den Eltern und den Stromablesern des E-Werks. Klein soll's sein. Eine passende Kunststoffplatte ist schnell gefunden, aber wie befestigen? Am Zähler einhängen ist Mikado, schaut man das Ding einmal schief an oder verrutscht es ganz leicht, war's das mit der Zählerei. Festschrauben geht auch nicht - wo denn auch. Also kleben - aber so, dass es rückstandsfrei ablösbar ist. Klebeband fällt weg, da es Klebereste hinterlässt und sowieso binnen Tagen abfällt. Epoxid oder jeder andere aushärtende Kleber hinterlässt auch bleibende Spuren und könnte als Manipulationsversuch gewertet werden. [[Datei:Bananen Frucht.jpg|thumb|Eine Banane, eisenreich und sehr bekömmlich (cc:by-sa Darkone)]] Zum Glück[tm] ist die Werbeindustrie nicht an mir vorbei gegangen. Tesa hat diese ziemlich überteuerten, kaugummiartige Klebestreifen: Powerstrips. Diese sollen sich rückstandsfrei und schnell wieder entfernen lassen. Erstaunlicherweise stimmt das sogar. Ein Versuch stellte unter Beweis, dass der Kauf eine gute Idee war. Der Plastestreifen hält bombig, lässt sich aber gleichzeitig spielend entfernen. Zurück zur Technik: Da ich nicht den kompletten Zähler abdecke, hatte ich etwas Zweifel an der Umgebungslichtabhängigkeit - zumal der Fototransistor auch mit der IR-LED am Testzähler keine allzu überzeugende Flanke lieferte. Ein Hochpass im Millihertz-Bereich in Form eines quasi beliebigen Kondensators eliminiert alle längerfristigen Änderungen im Signal. Halbwegs langsame Helligkeitsänderungen wirkten sich gerade mal im Millivoltbereich aus. Auch das Anleuchten mit einer Taschenlampe brachte die Schaltung nicht aus dem Tritt. Komisch war nur, dass, wenn der Zähler lief, eine leichte Wechselspannung im Signal war. Die Stromversorgung war es nicht, lt. Oszi astrein. Die Ursache: Die glänzende Scheibe ist mit schwarzen Strichen versehen, die von der Schaltung ebenfalls erfasst werden. Das hätte ich bei weitem nicht gedacht. (Ein spätere Test brachte die Gewissheit - unser Backofen beschleunigte das "Grundrauschen" um 7Hz). Zur Eliminierung des Ripples wurde nach dem Hochpass noch ein 100nF-Kondensator als Tiefpass eingesetzt, der zur Tilgung der Störung aber nicht vollständig ausreichte. <gallery> Datei:Nrg zaehler umlauf.png|Ein Umlauf, wie er direkt am Fototransistor gemessen wird Datei:Nrg zaehler rauschen.png|"Grundrauschen" der rotierenden Scheibe (ohne DC-Offset) </gallery> Die Leistungsaufnahme lässt sich anhand der Umlaufzeit wie folgt berechnen: <math> P=\frac{1}{t}\frac{\textrm{rot}}{\textrm{s}}\cdot \frac{1}{75}\frac{\textrm{kWh}}{\textrm{rot}}\cdot 3600 \frac{\textrm{W}}{\textrm{h}}\cdot 1000\frac{\textrm{W}}{\textrm{kW}} = \frac{1}{t}\frac{\textrm{1}}{\textrm{s}}\cdot \frac{3600\cdot 1000}{75}\textrm{Ws} = \frac{1}{t}\frac{\textrm{1}}{\textrm{s}}\cdot 48000\textrm{Ws} </math> Setzt man die im Screenshot ermittelten 42.6 Sekunden ein, erhält man eine Leistung von ~1127 Watt. Da die Leistung mit der Zeit exponentiell abnimmt, ist bei hohen Leistungsaufnahmen eine relativ hohe Auflösung der Zeit erforderlich. Da das Signal an dieser Stelle immer noch nicht Mundgerecht für den Mikrocontroller ist, soll es noch durch einen Operationsverstärker aufgearbeitet werden. Komischerweise läuft es bei mir mit OPs eigentlich immer auf einen Komparator hinaus, was aber ziemlich gut funktioniert. Hier der Stromlaufplan: <gallery> Datei:Nrg zaehler auswert.png|Auswerteschaltung Datei:Nrg zaehler pass.png|Zählersignal vor (blau) und nach (gelb) dem Filter </gallery> Links wird der Fototransistor in Sperrrichtung angeschlossen. Der 1µF-Elko und der nachfolgende 100k-Widerstand stellt einen Hochpass mit nicht näher definierter Grenzfrequenz (WolframAlpha sagt [http://www.wolframalpha.com/input/?i=1%2F%282*Pi*100kOhms*1%C2%B5F%29 1.592Hz]) dar. Die Frequenz ist ist im Hinblick auf [[:wpde:Hochpass:Ordnung]], Bauteiletoleranzen und der Zielfrequenz vermutlich nicht einmal ein Richtwert. Der folgende Hochpass hat eine Grenzfrequenz von ca. 16Hz. Hier gilt das gleiche Vertrauen wie in den Tiefpass. Aber alles kein Problem: Die Werte sind weitestgehend unkritisch. Es sind Umläufe im Millihertz-Bereich (also Umlaufdauern in der Größenordnung Sekunden bis Minuten) zu erwarten. Wären die beiden Stromzähler fast erschlagen. Fast, da einer der beiden zwei "Tachostände" hat. Die Wärmepumpe bekommt in der Nacht günstigeren Strom, dementsprechend soll auch der Zähler ausgewertet werden. [[Datei:Nrg tarifzaehler.jpg|thumb|Tarifzähler, rechts das Fähnchen zum Anzeigen des Tarifs]] Problem: die Anzeige besteht aus einem kleinen (2x5mm) Fähnchen, das sich je nach Tarif gerade mal um 5mm bewegt. Das wird schon 'ne Ecke schwieriger. Meine Ideen belaufen sich momentan auf Laserpointer oder einer Linse/Lochblende vor der LED. Da wird die Tarifumschaltung evtl. noch ein bisschen warten müssen. [[Datei:Nrg_relais_freigabe.jpg|thumb|Relais für die Stromfreigabe, mit LED]] Einfacher ist hingegen die Erkennung der Stromfreigabe. Da die Wärmepumpe mit ca. 5kW Leistungsaufnahme ein doch recht großer Verbraucher ist, wird ihre Stromversorgung zu Spitzenzeiten (Mittags und Abends) unterbrochen. Da bei uns niemand so genau weiß, wann diese Zeiten sind, man aber sein Dusch- & Badeverhalten zumindest an sonnenarmen Tagen besser danach anpasst (sonst gibt’s eine regelrechte Erfrischung), landen die Schaltzeiten ebenfalls im Protokoll. ==Wärmepumpe== Die Kenndaten der Wärmepumpe stehen nicht ohne Grund NICHT in der Liste. Ich habe es über den Diagnose-Anschluss der Regelung zwar geschafft, dem Teil Messwerte zu entlocken, jetzt kommt das große aber: Man muss die Daten aktiv abfragen. Das wäre soweit nicht schlimm, hinderlich ist nur, dass: * der Hersteller (Danfoss) nichts zum Protokoll herausrückt * die Schnittstelle ewig langsam ist * es anscheinend keine Sicherheitsschichten im Protokoll gibt Letzteres hört sich zwar harmlos an, ist in Verbindung mit dem relativ unbekannten Protokoll und der Tatsache, dass man Befehle zum Auslesen der Messwerte senden muss, richtig gefährlich. Über die Diagnoseschnittstelle kann man den Regler deaktivieren und auf manuelle Steuerung gehen. Wenn man daneben steht und den Not-Aus drücken kann, ist das akzeptabel, mir ist der unbeobachtete Betrieb einer solchen Anordnung definitiv zu heiß. Da verzichte ich lieber zugunsten des längerfristigen Familienfriedens. ==Solaranlage== Hier wird es meiner Meinung interessant. Bei der Wärmepumpe kann man in etwa sagen, was an Wärme rein bzw. raus kommt, die Solaranlage hat da weitaus mehr Einflussgrößen. Ok, eigentlich nur die Sonneneinstrahlung, die ist dafür aber auch recht flexibel. Wie im Artikel [[VBus-Decoder]] vorgestellt, habe ich eine Protokollschnittstelle zu Solar-Regelern von Resol geschrieben, zu denen auch unsere Viessmann-Regelung kompatibel ist. Zu Beginn war es eigentlich gedacht, den Decoder direkt auf dem Net-IO laufen zu lassen. Da es im Heizkeller (der örtlich getrennt zum Zählerkasten ist) noch ein paar weitere aufzeichnungswürdige Datenquellen gibt, wird sich dort auf lange Sicht ein zweiter Mikrocontroller einfinden. Der Grund: im Februar 2010 (siehe [http://hobbyelektronik.org/b/?p=199 Blogeintrag]) hatten wir einen massiven Druckabfall in der Solaranlage, was zum Komplettausfall derselben führte. Zwar wurde die Störung von der Steuerung vermutlich erkannt und gemeldet, aber was man nicht weiß, macht einen sprichwörtlich nicht heiß. Deshalb soll hier später der Systemdruck und ggf. auch der Durchfluss auf Wärmemittelseite ermittelt werden. Theoretisch reicht das Messen nur eines Parameters, aber was, wenn das Manometer durch eine Verstopfung oder der Durchflussmesser durch ein Leck (eher unwahrscheinlich) einen falschen Wert liefert? Der Durchflussmesser und das Manometer könnte zwar auch direkt an die Regelung der Solaranlage angeschlossen werden. Allerdings möchte ich an dieser Stelle nicht mit fremder Hardware experimentieren. Was mit der Solarregelung lt. Resol-Support ohne Probleme geht, ist das anbringen weiterer Temperatursensoren. Diese werden, sofern nicht anders konfiguriert, von der Regelung ignoriert. Die gemessenen Werte werden aber trotzdem auf dem Display angezeigt und über den VBus übertragen, also perfekt für mein Vorhaben. Das Problem ist nur: Wie kommt man halbwegs günstig an die passenden Temperatursensoren? Beim lokalen Heizungsbauer war Stand 02/2010 nichts Gebrauchtes zu holen, was in Hinblick auf die Temperaturen auch verständlich ist: Wer erneuert im strengen Winter freiwillig seine Zentralheizung? Bei eBay gehen die Preise deutlich auseinander. Im August bin ich auf wirklich günstige PT1000 von einem österreichischen Händler gestoßen: 5 Stück für nicht mal 4 Euro. Im Brief (der nur 3 Tage später in der Post war) waren sage und schreibe 9 Sensoren! TODO: Bild der Sensoren/Trägerplatine Auf Trägerplatinen gelötet ging es siegessicher in den Keller. Nur leider ließen die beiden Sensoren die Regelung kalt. Statt auf das Datenblatt des fast baugleichen Resol-Pendanten zu vertrauen hätte ich lieber gemessen, mit welchen Sensoren ich zu tun habe: Das ist neben der fehlenden RS232-Schnittstelle anscheinend die zweite Viessmann-Extrawurst am Regler: keine PT1000. Also müssen die Sensoren selber ausgelesen werden. Eigentlich kein Problem: Spannungsteiler, Messverstärker, ADC und gut. Laut Suchmaschine nicht ganz. Die gefundenen Schaltungen sehen deutlich aufwändiger aus, über einen Multiplexer direkt hinter dem Spannungsteiler (bzw. der Konstantstromquelle) möchte ich gar nicht nachdenken. Dann doch lieber I²C oder 1-Wire im Heizungskeller. Günstigste Alternative: Vorerst nichts. '''Update 10.10.2010:''' Weasel (IRC) ist beim Anblick der Kennlinie der Temperatursensoren in der Anleitung des Vitosolic 200 blitzschnell darauf gekommen, dass es sich um PT500-Elemente handeln müssen, die jedoch nur für sehr teuer Geld erhältlich sind. Mein anfänglicher Scherz vonwegen 2 PT1000 parallel ergibt PT500 hat sich als gar nicht so dumm erwiesen: Idealerweise sind die Widerstände der Sensoren bei gleicher Temperatur ebenfalls gleich, Durch Parallelschaltung zweier PT1000 kann man sie problemlos an der PT1000 betreiben! Da ich sonst nichts mit meinen 9 Sensoren anzufangen wusste, fristen jetzt 8 dieser als 4 Fühler im Keller ihr dasein: Zwei erfassen die Ein- und Auslasstemperatur an der "Primärseite" der Wärmepumpe, einer sitzt im Warmwasserspeicher in oberster Schicht und der 4. misst (da mir noch nichts besseres einfiel) die Raumtemperatur im Heizkeller, die mangels Isolierung der Rohre deutlich zu hoch ist. '''Update-Ende''' === Was kommt rein? === Auf der Unterseite [[Energieerfassung/Solarleistung]] habe ich beschrieben, wie man anhand einiger Parameter die Leistung der Solaranlage berechnen kann ==Wasserzähler== Zum Energiehaushalt gehört selbstverständlich auch der Wasserverbrauch. Da der zugehörige Zähler wieder einen Raum weiter und deutlich schlechter als die Stromzähler nachstellbar ist (und ich dadurch zwangsläufig längere Zeit im Holzkeller stehen müsste), habe ich mir über dessen Erfassung noch keine größeren Gedanken gemacht. Allerdings hatte ich schon ein paar Grundgedanken zum Thema Wasser: ===Wärme Extrem=== Die Energie, die man in den Boiler mühevoll hineingesteckt hat, will man irgendwann auch wieder herausnehmen. Aber zu welchem Anteil geht sie wohin? Nicht dass drei Stromzähler schon genug wären – wir verbrauchen die Wärme des Wassers auch auf drei Methoden: Brauchwasser, Wandheizung und in ein paar Räumen liegt zusätzlich eine Fußbodenheizung. Neben dem Wasserverbrauch wäre es interessant, den Energiebedarf an Wärme genau zu ermitteln. Mit der Formel E=c*m*\deltaT kann man anhand der spezifischen Wärmekapazität (c), der Masse (m) und des Temperaturunterschieds (deltaT) die Energie berechnen. C ist mit 4.19 kJ/(kg*K) bekannt, der Temperaturunterschied kann einfach gemessen werden. Nur wie kommt man an die Masse? Einfacher als man denkt: Mit einem Wasserzähler kann man in Liter bzw. m³ die Menge berechnen, über die Dichte kommt man an die Masse. Für die Bestimmung der Wärmemenge braucht man also fünf Dinge: Einen Wasserzähler, zwei Temperatursensoren, ein Rechenwerk und einen Installateur, der den Zähler anschließt. Da ersteres mit digitalem Ausgang zusammen mit letzterem für wenig Geld nicht einfach aufzutreiben ist und meine Eltern dann wahrscheinlich Angst vor der totalen Überwachung bekommen, lasse ich es bei der Idee. Vorerst. =Hardware= ==Großhirn== In der ersten Ausbaustufe besteht die Hardware hauptsächlich aus einem etwas aufgewerteten [http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin]. Zur Erweiterung wurde das [[AVR-NET-IO-Shield]] entwickelt und verwendet. Auf diesem befindet sich die Spannungsregelung (Schaltwandler), die den Stromverbrauch im gegenüber den Linearreglern am „Standard-NET-IO“ deutlich verringern. Daneben trägt es die Auswerteschaltung für die beiden Stromzähler, die Anschlussmöglichkeit für ein Character-LCD, eine Halterung für Bedienelemente sowie einen Steckplatz für weitere Hardware. Dies war nötig, da ich mir noch keine Gedanken über die Auswertung der Tarife und der Stromfreigabe gemacht habe, aber die bereits vorhandenen Funktion (Stromzähler & Solaranlage) bereits zur Verfügung haben wollte. <gallery> Datei:Nrg shield.jpg|Shield des Großhirns Datei:Nrg grosshirn.jpg|Hirn von oben </gallery> ==Kleinhirn== Wie im Abschnitt Solaranlage beschrieben, soll im Heizkeller später ein weiterer Mikrocontroller sein Zuhause finden. Dies wird vermutlich erst nach der kompletten Fertigstellung des Großhirns erfolgen. =Software= Die Software kann man im Groben in drei Teile untergliedern. Auf der einen Seite die Firmware(s) der Hardware für die Energieerfassung, dann die Software auf dem Webserver und der Clientsoftware. Die Dreierteilung habe ich gewählt, da es am günstigsten und wahrscheinlich auch am effektivsten ist. Speicher auf dem AVR-NET-IO ist knapp und somit wertvoll. Gleichzeitig ist es für meinen Webhoster ok, dass ein „Robot“ alle paar Stunden auf den Webspace zugreift. Da der Webserver sowieso 24/7 läuft und sich mit hobbyelektronik.org langweilt, verhält es sich Kosten- und Energieneutraler, wenn er die Datenhaltung übernimmt, anstatt dass ich zuhause einen PC-Server vorhalte (der dann auch die Erfassung der Daten übernehmen könnte). Da das herumliegende Notebook im Idle 20W und das „Großhirn“ lediglich 1,2W benötigt, war die Entscheidung einfach. ==Großhirn== Die Firmware des umgebauten NET-IO basiert auf [http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig. Zunächst wurde der Code auf das Pollin-Board angepasst. ===Display=== Da das LC-Display den aktuellen Zustand der Anlage anzeigen soll und der mitgelieferte Quelltext nicht zuverlässig funktionierte, habe ich die LCD-Bibliothek von [http://homepage.hispeed.ch/peterfleury/ Peter Fleury] übernommen und für die Anwendung erweitert. Da das 4x16-Character-Display etwas wenig Platz für Infos bietet, sind mehrere Ansichten implementiert, die u. a. Details zu den Stromzählern, der Solaranlage oder Debuginformationen anzeigt. <gallery> Datei:Nrg lcd 1.jpg|Home-Screen mit Datum und Uhrzeit Datei:Nrg lcd 2.jpg|Aktueller Stromverbrauch Datei:Nrg lcd 3.jpg|Solardaten: Kollektortemperatur, Pumpenlast und Speichertemp. Datei:Nrg lcd 4.jpg|Debuginfos, Timeouts des TCP/IP-Stacks und Refresh des NTP-Clients </gallery> ===Energie-Zähler=== Für die Messung des Strom- und Wasserbedarfs werden zwei Timer verwendet. Der 8-Bit-Timer im AVR übernimmt das Sampling der Eingänge, die mit ca. 60Hz abgefragt werden. Um Störungen zu unterdrücken, werden die Messwerte durch eine 8-Bit-Variable geschoben. Sind die ersten 4 Bit 0 und die restlichen 1, wird dies als Umlauf gewertet. Optimaler wäre hier, den [[wpde:Hamming-Abstand|Hamming-Abstand]] zwischen den eingelesenen Daten und dem Bitmuster 00001111<sup>b</sup> zu ermitteln und den Umlauf beim Abstand 1-2 zu werten. Dadurch können weitere unbeabsichtigte Fehlmessungen unterdrückt werden. Der zweite Timer, der als allgemeiner Zeitgeber verwendet wird, soll auch die Umlaufzeiten der Stromzähler messen. Da die Auflösung von einer Sekunde gerade bei hohen Stromaufnahmen zu sehr ungenauen Werten führt, habe ich den Intervall auf 0.1 Sekunden erhöht. Damit der Tag nicht in nur knapp zweieinhalb Stunden dauert, verringert ein Software-Prescaler die Ticks um den Faktor 10. ===Solaranlage=== Die Solaranlage wird über den [[VBus-Decoder]] erfasst. Um immer gültige Datensätze zu haben, gibt es zwei Variablen zur Datenhaltung: Das temporäre Struct wird fortwährend vom Decoder gefüllt. Sind gültige Daten vorhanden, werden die Werte mit memcpy übertragen. ===Bereitstellung der Daten=== [[Datei:Nrg json.png|thumb|Exemplarischer JSON-Datensatz]] Um den Verlauf des Energiebedarfs zu verfolgen, werden die Messwerte auch historisch gespeichert. Im internen RAM des AVRs passen insgesamt 15 Datensätze. Um ein ausgewogenes Verhältnis zwischen Speicherdauer, historischer Genauigkeit und dem Speicherplatzbedarf in der Datenbank zu halten, habe ich ein Zeitraster von 15 Minuten gewählt. Dadurch können Daten von 3.5 Stunden vorgehalten werden. Der aktuellste Datensatz ist aufgrund der laufenden Erfassung immer ungültig und ist damit außen vor. Zum Datenaustausch habe ich das schlanke [http://www.json.org JSON]-Format gewählt. Im Gegensatz zu XML hat es nur wenig Overhead und kann mit JavaScript extrem schnell verarbeitet werden (da es im Prinzip JavaScript ist). Zum Umwandeln habe ich ein paar einfache Funktionen geschrieben, um Texte und Variablen in den Ausgabepuffer des Stacks zu schreiben. Der JSON-Datenstrom wird mit einfachen Zeichenverkettungen erzeugt. Das ist zwar nicht unbedingt übersichtlich, dafür aber halbwegs performant und platzsparend. Auf diese Weise werden zwei „Dateien“ bereitgestellt: current.json und history.json. Erstere enthält aktuelle Messdaten, wogegen history.json die letzten 15 erfassten Datensätze enthält. Der Einfachheit halber werden die Daten direkt per HTTP bereitgestellt. Dadurch können sie direkt vom Webbrowser oder vom Webserver abgerufen werden. ==Server-Software== Da bei Hetzner (und den meisten anderen Anbietern) CronJobs nicht inklusive sind, müssen die Daten vom NET-IO zum Webspace übertragen werden. Leider ist es mit dem verwendeten Netzwerkstack etwas umständlich, HTTP-Requests mit Daten im Schlepptau abzusetzen. Deshalb wird das Pferd von hinten aufgezäumt: Der AVR-NET-IO sendet eine leere HTTP-Anfrage an den Webserver. Hinter dem aufgerufenen URL befindet sich ein Script, das dann die history.json vom „Großhirn“ lädt, verarbeitet und in die Datenbank schreibt. Gleichzeitig prüft das Script, ob aus den Daten Probleme in der Anlage ersichtlich sind und meldet diese per E-Mail an uns. (noch nicht implementiert) Weiter befindet sich auf dem Server (noch k)ein Script zur Auswertung und Bereitstellung der historischen Daten, das vom Client ausgelesen und präsentiert wird. ==Client== Der Client ist keine Software, die lokal auf dem Computer installiert wird. Es handelt sich streng genommen um eine Internetseite. Da sie jedoch durch JavaScript wesentlich mehr Intelligenz als „normale“ HTML-Dokument enthält, spreche ich hier gerne vom Client. Dieser existiert (aus Ermangelung der vollständigen Serversoftware) momentan nur in einer Live-Version, die die aktuellen Messwerte sowie die historischen Daten direkt aus dem „Großhirn“ anzeigt und nicht weiter auswertet. =Downloads= Aktuelle Firmware, EAGLE-Dateien des Shields (ohne V-Bus-Pegelwandler): [[Datei:Energieerfassung Firmware.zip]] =Nerviges/Todo= *Die interne Uhr hat eine sehr hohe Gangabweichung. Macht sich trotz kurzer NTP-Refresh-Intervallen bemerkbar *Der Speicher für die historischen Daten ist sehr klein. Bei Ausfall der Internetverbindung/Server/Cronjob gibt es zu schnell Lücken *Erfassung des Wasserzählers *Erfassung Außentemperatur =Trivia= ==Fehler & Probleme== Sind wir ehrlich: ein Nagel in der Wand ist ein Nagel in der Wand und kein Projekt ;) Warum ich das schreibe: ein Nagel ist schnell paar Zentimeter in den Putz geklopft, bei einem Projekt kann wesentlich mehr schiefgehen als abgeplatzter oder eingedellter Putz: *Zu blöd für den Schaltungsaufbau: [http://hobbyelektronik.org/b/?p=202 „Eine Schlange würde…“] *Großer Knoten im Hirn wegen der Erzeugung/Bereitstellung der JSON-Datan *Fehlerhaftes Package des LCDs am Großhirn *Kurzschluss der Stromzähler-LEDs am Großhirn (Pads der LEDs zu groß und Widerstände gegen GND geschaltet) *Die PT1000-Temperaturfühler funktionieren zwar an RESOL-Regelungen und nicht an denen von Viessmann *[http://hobbyelektronik.org/b/?p=292 LM358 ungleich LM358]: Plötzlich habe ich keine Daten mehr von der Solaranlage empfangen – jetzt zumindest Cat5 im Heizkeller *Alte LCD-Lib im Großhirn-Projekt gelassen, es einen halben Nachmittag nicht gemerkt und gewundert, warum die Änderungen auf dem AVR nicht ankommen ==Weblinks/Siehe auch== *[http://hobbyelektronik.org/b/?cat=23 Blogeinträge zum Projekt] *[http://www.pollin.de/shop/dt/MTQ5OTgxOTk- AVR-NET-IO] von [http://www.pollin.de Pollin] *[http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex ETH_M32_EX] von Ulrich Radig *[http://www.json.org/json-de.html Einführung in JSON] *[[VBus-Decoder]] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] a5c76bcc5e27874fa5d645c2a0a72b134009e791 Hauptseite 0 1 1301 1262 2019-03-16T17:01:41Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] 4b0b05184d09cfd85ac46bc5e5331ea8a45cc211 1326 1301 2019-03-21T21:10:11Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert 41c42a7d73849db461a1a6d51516d7e2f1d60f7d Hobbyelektronik.org:Impressum 4 4 1302 1197 2019-03-16T17:32:08Z Chris 2 /* Verschlüsselung */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) d011413ef7b437ece689309690889b4ca59cf0ab 1303 1302 2019-03-16T17:48:26Z Chris 2 Spenden wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Andersrum: es gab noch nicht einmal eine Antwort auf die Mail. Da merkt man, wo deren Herz schlägt. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Wie auch immer. Da mich diejenigen, denen ich "übrige" Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das "schlechte Gewissen" zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet), darf einen Betrag - nach völlig eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine "Win-Win-Win-Situation": Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spendet an eine Organisation, die ihr für gut haltet, der Betrag ist mir egal. Wenn ihr möchtet, könnt ihr auch auf hobbyelektronik.org/spende verweisen. Alles Kann, kein Muss. Wichtig ist mir nur, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. "Absolut richtig" zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krebshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und "Bettelbriefe" steckt. * Fragwürdig halte ich ebenfalls PeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kirche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Kirche unterschiedliche Dinge.) =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) 704b130123b7cab3bcb9e35b84f2392c4df28f4d 1304 1303 2019-03-16T17:48:54Z Chris 2 Reihenfolge korrigiert wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org<br /> E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder einfach auf sks-keyservers.net suchen) Kein Facebook, kein WhatsApp und auch keine anderen Plattformen. Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Andersrum: es gab noch nicht einmal eine Antwort auf die Mail. Da merkt man, wo deren Herz schlägt. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Wie auch immer. Da mich diejenigen, denen ich "übrige" Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das "schlechte Gewissen" zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet), darf einen Betrag - nach völlig eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine "Win-Win-Win-Situation": Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spendet an eine Organisation, die ihr für gut haltet, der Betrag ist mir egal. Wenn ihr möchtet, könnt ihr auch auf hobbyelektronik.org/spende verweisen. Alles Kann, kein Muss. Wichtig ist mir nur, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. "Absolut richtig" zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krebshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und "Bettelbriefe" steckt. * Fragwürdig halte ich ebenfalls PeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kirche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Kirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) db3b809449bb25cd4185074a037aeb6b58b02d37 Datei:Pirozeda hat 0.1 adum.jpg 6 570 1305 2019-03-21T20:57:41Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Pirozeda hat 0.1 adum assy.png 6 518 1306 1210 2019-03-21T20:58:02Z Chris 2 Chris lud eine neue Version von [[Datei:Pirozeda hat 0.1 adum assy.png]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 adum hotfix.jpg 6 571 1307 2019-03-21T20:58:21Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Pirozeda hat 0.1 adum hotfix.png 6 572 1308 2019-03-21T20:58:53Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Pirozeda hat 0.1 adum sch.png 6 519 1309 1211 2019-03-21T20:59:19Z Chris 2 Chris lud eine neue Version von [[Datei:Pirozeda hat 0.1 adum sch.png]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 assy optional.png 6 520 1310 1212 2019-03-21T21:00:01Z Chris 2 Chris lud eine neue Version von [[Datei:Pirozeda hat 0.1 assy optional.png]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 buchsenleiste pins.png 6 573 1311 2019-03-21T21:00:11Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Pirozeda hat 0.1 direct assy.png 6 521 1312 1213 2019-03-21T21:00:23Z Chris 2 Chris lud eine neue Version von [[Datei:Pirozeda hat 0.1 direct assy.png]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 direct sch.png 6 522 1313 1214 2019-03-21T21:00:43Z Chris 2 Chris lud eine neue Version von [[Datei:Pirozeda hat 0.1 direct sch.png]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 minidin.jpg 6 574 1314 2019-03-21T21:01:00Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Pirozeda hat 0.1 opto.jpg 6 575 1315 2019-03-21T21:01:14Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Pirozeda hat 0.1 opto assy .png 6 576 1316 2019-03-21T21:01:27Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Pirozeda hat 0.1 opto sch.png 6 525 1317 1217 2019-03-21T21:01:38Z Chris 2 Chris lud eine neue Version von [[Datei:Pirozeda hat 0.1 opto sch.png]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Datei:Pirozeda hat 0.1 pfosten.jpg 6 577 1318 2019-03-21T21:01:52Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:EBay-RTC-Module.jpg 6 578 1319 2019-03-21T21:02:18Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 1320 1319 2019-03-21T21:03:17Z Qsysopr 1 Qsysopr verschob die Seite [[Datei:Rtc.jpg]] nach [[Datei:EBay-RTC-Module.jpg]], ohne dabei eine Weiterleitung anzulegen: dummer Name wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Pirozeda-HAT 0 533 1321 1244 2019-03-21T21:03:55Z Chris 2 Seite großzügig aktualisiert wikitext text/x-wiki Wie bereits im [[Pirozeda|Hauptartikel]] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADMUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar Geschmackssache aber in Hinblick auf Platz das Beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== '''Noch nicht aufgebaut und getestet.''' Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist, dass neben der gemeinsamen Masse mit der Solaranlage Backfeed entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Diese Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== '''Aufgebaut und erfolgreich getestet.''' Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_opto_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_opto_assy.png|Bestückungsplan mit Optokoppler pirozeda_hat_0.1_opto.jpg|Aufgebauter HAT - es passt sogar ein MJ-Quarz </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R13, R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== '''Aufgebaut und weitestgehend erfolgreich getestet.''' Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator pirozeda_hat_0.1_adum.jpg|Aufgebauter HAT mit Hotfix </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 1 || R9 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} Bei der Schaltungsentwicklung hat sich leider ein dummer Fehler eingeschlichen. Ich dachte nicht daran, dass der ADuM !RES treiben wird - und das v.a. nach GND. Kann man zwar halbwegs in Software umgehen, ist aber Mist. '''Die einfachste Fehlerbeseitigung ist, R10 einfach nicht zu bestücken.''' Der ADuM1301 ist trotz des fehlenden Features die günstigste Lösung. Der Reset des Mikrocontrollers (und damit das Wechseln in den Bootloader) kann auch per Kommando ausgelöst werden. Wer will, kann jedoch auch einen Hotfix implementieren: Dazu muss das obere Pad von R10 von der Leiterbahn getrennt werden (rot). Auf den Pads von R18 (rechts) und R10 kann nun ein BSS138 verdreht aufgesetzt werden. Das obere Pad muss dabei noch mit Masse verbunden werden (orange). <gallery> Pirozeda_hat_0.1_adum_hotfix.png Pirozeda_hat_0.1_adum_hotfix.jpg </gallery> Achtung: Auch mit diesem Hotfix gibt es einen Fallstrick: Ist die "Raspberry Pi"-Seite Stromlos, geht der Ausgangspin des ADuM auf high, folglich hängt Reset bei low (aktiv). Kann seine Vorteile haben, zum Flashen des Mikrocontrollers aber eher unpraktisch. =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== '''Aufgebaut und erfolgreich getestet.''' Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEProm ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SJ1 || || SJ || |- | 1 || C6 || 100n || C0603 || X7R-G0603 100N |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 2 || R3, R4 || 3k3 || R0603 || RND 0603 1 3,3K |} Aktuell gibt es noch keine weitere Unterstützung hierfür. Es handelt sich also eher um ein Gimmick. Den EEProm kann man sich recht günstig von eBay-Modulen "abernten" - einfach im nächsten Abschnitt weiterlesen. ==Real-Time-Clock== '''Aufgebaut und erfolgreich getestet.''' Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R11, R12 || 0 || R0603 || RND 0603 1 0 |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 2 || R6, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. Der Levelshifter kann nach ersten Testes getrost weggelassen werden. Wem der DS1307 bei Reichelt zu teuer ist, kann sich bei eBay ein Modul mit dem Chip, passendem Quarz (der zufällig dem verwendeten entspricht) und einem ebenfalls passenden EEProm besorgen. Der Batteriehalter passt im aktuellen Design leider nicht. <gallery> EBay-RTC-Module.jpg|RTC-Modul als Bauteilspender </gallery> ==Option: I²C(-OLED) + Taster== '''Noch nicht aufgebaut und getestet.''' Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |} ==Status-LEDs== '''Aufgebaut und erfolgreich getestet.''' Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 3 || R24, R25, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || LED1 || gn || CHIP-LED0603 || |- | 2 || LED2, LED3 || or || CHIP-LED0603 || |} LED1 (mitte) zeigt Aktivität an, LED2 (unten) ist mehr oder weniger die Power-LED. Mehr oder weniger, da sie beim Start der Firmware aktiviert wird (nicht aber im Bootloader). Dadurch kann man sehr schnell erkennen, ob sich die Hardware in einem Bootloop befindet. LED3 (oben) kann vom Raspberry Pi angesteuert werden. Standardmäßig sind in der <code>config.h</code> folgende Zeiten für LED1 eingestellt: * Start der Anwendung: 250 ms * Korrekt empfangene Nachrichten: 10 ms * Fehlerhaft empfangene Nachrichten: 200 ms Damit kann man auf den einen Blick erkennen, ob Daten vernünftig ankommen und verarbeitet werden können. =Aufbau der Hardware= ==Bestücken der Leiterkarte== Die Hardware kann im Prinzip in beliebiger Reihenfolge aufgebaut werden. Trotzdem ist es ratsam, die großen/hohen Bauteile zuletzt aufzulöten. Die Steckkräfte einer 2x20 Buchsenleiste sind vergleichsweise groß. Diese können reduziert werden, indem nicht verwendete Pins aus der Buchsenleiste entfernt werden. Um diese nicht wieder (fragt nicht) zurückstecken zu müssen, hier eine Auflistung der benötigten Pins: 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 15, 17, 20, 25, 27, 88, 30, 34, 37, 39. Oder einfach als Bild: <gallery> Pirozeda_hat_0.1_buchsenleiste_pins.png|benötigte Pins (blau markiert) </gallery> Der Wannenstecker lässt sich am einfachsten auflöten, wenn man die Pads auf einer Seite (egal welche) der Leiterkarte bisschen stärker verzinnt. Dadurch kann man den Konnektor ein wenig verklemmen und vor dem Verlöten besser ausrichten. ==Zuleitung== Als Zuleitung habe ich für die ersten Muster den Artikel LIYY 614 (Steuerleitung 6x0,14mm², ungeschirmt) von Reichelt verwendet. Beim Bestellen habe ich leider mehr auf den Preis als die Schirmung geachtet. In Hinblick darauf, dass der Schirm der Buchse im Regler eh nicht mit Masse verbunden ist, ist es eine ziemliche Fummelarbeit, diese mit dem Massepin zu verbinden. Erkenntnisse über die maximale Leitungslänge gibt es noch nicht. Der Vorteil dieser Leitung ist: die Adern können direkt im Pfostenverbinder verpresst werden: <gallery> Pirozeda_hat_0.1_pfosten.jpg </gallery> Ich habe mich für folgende Farbgebung entschieden, beim Pinmapping selbst gibt es keine Wahl: {| class="wikitable" ! Mini-DIN || Signal || Farbe || Wannenstecker |- | 3 || MISO || grau || 1 |- | 4 || GND || braun || 3 |- | 5 || 3V3 || rosa || 5 |- | 6 || MOSI || grün || 2 |- | 7 || SCK || gelb || 4 |- | 8 || !CS || weiß || 6 |} Beim Mini-DIN-Stecker sollte darauf geachtet werden, die äußere Hülle nicht komplett über den Rest zu stülpen, da die Buchse beim Regler ziemlich weit nach innen versetzt ist: <gallery> Pirozeda_hat_0.1_minidin.jpg </gallery> =Firmware= Grundsätzlich läuft die Firmware des Originaldesign auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel und viele neue Features fehlen: Ab 0.2: * Status-LEDs * Uptime-Counter * Messung der Versorgungsspannung * Anzeigen von Bootinformationen ** Resetgrund ** Anzahl der vorherigen Reboots ** Dauer der vorherigen Uptime ** Fusecheck ** Watchdog-Info ** Aktivierte Nachrichten * Neustart + Wechsel in den Bootloader per Kommando * Statistik über empfangene Nachrichten (optional) * Timestamps (optional, aktuell nicht kompatibel mit der Backend-Software) * Erneutes übertragen der Headerinformationen * Kann die Firmware bei einem "Katzen-Paket" miauen. Einfach nur weil. ==Konfiguration== Einige der Features müssen vor dem Kompilieren aktiviert bzw. eingestellt werden. Die Schalter und Defines hierfür befinden sich in zwei Header-Dateien: <code>config.h</code> * <code>PIROZEDA_KITTY_DEBUG</code>: Anzeigen der "Katzen-Pakete" (Vorgabe: inaktiv) * <code>PIROZEDA_TIMESTAMPS</code>: Anzeigen der Timestamps (Vorgabe: inaktiv) * <code>PIROZEDA_WDT_TIMEOUT</code>: Timeout des Watchdogs (Vorgabe: 4 s) * <code>PIROZEDA_UPTIME</code>: Führen der Uptime, abrufbar über den Befehl (Vorgabe: aktiv) * <code>PIROZEDA_SUPPLY_AVGCNT</code>: Anzahl der Messwerte für die Mittelwertbildung der Systemspannung (Vorgabe: 10, maximal: 32) * <code>PIROZEDA_HEADERCNT</code>: Anzahl der Kopfzeilen-Datensätze, die nach dem Start oder Befehl <code>header</code> angezeigt werden (Vorgabe: 200, maximal: 255) * <code>PIROZEDA_STATUS_LED_BOOT</code>: Leuchtdauer der Status-LED nach dem Start (Vorgabe: 100 -> 250 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXOK</code>: Leuchtdauer der Status-LED bei empfangenem Paket (Vorgabe: 4 -> 10 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXERR</code>: Leuchtdauer der Status-LED bei einem Fehler (Vorgabe: 80 -> 200 ms, maximal: 255) * <code>BOOTLOADER_PASSWORD</code>: "Passwort" zum Wechsel in den Bootloader (Vorgabe: "FwUp", maximal 4 Zeichen, darf keine Teilstrings von Befehlen enthalten) <code>prozeda_cfg.h</code> * <code>PROZEDA_USE_COLUMN_NAMES</code>: Verwenden der Spaltennamen (irrelevant für Pirozeda) * <code>PROZEDA_SUPPORT_DISPLAY</code>: Aktiviert den Empfang von Displaydaten (Vorgabe: aktiv) * <code>PROZEDA_SUPPORT_HEADER</code>: Aktiviert den Empfang von Kopfzeilen-Datensätzen (Vorgabe: aktiv) * <code>PROZEDA_IGNORE_KITTY</code>: Ignorieren von Katzen-Paketen, andernfalls werden Fehler ausgegeben (Vorgabe: aktiv) * <code>PROZEDA_MSG_MAXTICKS</code>: Ticks, nach denen ein Paket als abgeschlossen erkannt wird, sollte nur bei Anpassung der CPU-Frequenz angepasst werden (Vorgabe: 3) ==Befehle== Neu ist ab v0.2, dass Befehle an den Mikrocontroller gesendet werden können. Je nach Konfiguration sind dies: * <code>reset</code>: Neustart * <code>uptime</code>: Anzeige der Laufzeit * <code>bootinfo</code>: Anzeigen der Infos, die auch beim (Neu-)Start angezeigt werden * <code>header</code>: Header werden gemäß <code>PIROZEDA_HEADERCNT</code> erneut ausgegeben * <code>stats</code>: Anzeigen der Statistik über empfangene Nachrichten und Empfangsfehler Alle Befehle sind Case-sensitive. ==Flashen der Firmware== Mit den Möglichkeiten steigt die Komplexität. Dadurch dass der die Hardware für die Verwendung mit und ohne Bootloader ausgelegt ist, gibt es mehrere "Pfade" für das Flashen. Wer auf Nummer sicher gehen will, lädt einfach Bootloader und Firmware auf den Mikrocontroller herunter. Selbst wenn man "nur" die Variante mit unidirektionalem UART hat - die Brücken Versorgung und für den UART zum Mikrocontroller ist schneller gelötet als die Stiftleiste für den ISP-Port. Das Einlöten einer wahnsinnig hohen Stiftleiste kann übrigens umgangen werden, indem eine Stiftleiste in das Programmierkabel gesteckt und im Footprint der Buchse "verkeilt" wird. Wirklich keine Dauerlösung aber im Idealfall muss man es nur einmal machen. ===Über Raspberry Pi=== Zunächst muss, wenn nicht schon geschehen, über <code>sudo raspi-config</code> das SPI-Interface aktiviert (reboot nicht vergessen) und [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer#Installation_der_Compiler AVRDUDE installiert] werden. Den Regler vom HAT trennen, nicht vergessen, dass R10 oder der Hotfix entfernt werden muss, falls der ADuM-Isolator verwendet und einseitig versorgt (also nicht auf dem Raspi steckt) wird und anschließend den SPI-Port mit SV2 verbinden. {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin |- | MISO || 1 || BCM 9 || 21 |- | 3V3 || 2 || 3V3 || 17 |- | SCK || 3 || BCM 11 || 23 |- | MOSI || 4 || BCM 10 || 19 |- | !RES || 5 || BCM 25 || 22 |- | GND || 6 || GND || 20 |} ====Mit Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = FC }} Die empfohlene Variante (auch wenn man nicht beabsichtigt, den Bootloader zu nutzen). Mit Bootloader sind das folgende Befehle: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0xFC:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_fboot_0.2.hex" </source> ====Ohne Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} 'cause I ain't gonna judge you <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_0.2.hex" </source> ==Update der Firmware== In Sachen Bootloader bin ich ein großer Fan von [https://www.mikrocontroller.net/articles/AVR_Bootloader_FastBoot_von_Peter_Dannegger Peter Danneggers Fastboot]. Er ist klein, schnell und zuverlässig. Um einen kleinen Unterschied zu machen, lautet das Passwort zum Starten nicht "Peda" sondern "FwUp", was ein kleines Problem mit sich bringt. "Peda" ist nicht nur der Spitzname vom Autor, das "a" wird zur automatischen Baudratenerkennung verwendet. Das von mir gewählte Passwort hat das nicht zu bieten. Was mir bei der Verwendung von [https://luani.de/projekte/updateloader/ UpdateLoader] aufgefallen ist: es funktioniert trotzdem. Ganz einfach, weil der Autor ein "a" voranstellt. Das funktioniert dann auch mit so gut wie allen anderen Download-Tools. ===Mit Bootloader=== Das Firmware-Update funktioniert nur bei bidirektionaler UART-Kommunikation mit dem Mikrocontroller, also bei der Variante Direkt und ADuM-Isolator. Wenn man mutig ist, kann man bei der Optokoppler-Variante R19 und R27 bestückt werden. In jedem Fall muss die Mikrocontroller-Seite mit Strom versorgt werden, also am einfachsten am Solarregler angeschlossen lassen. Berhard M. (boregard) hat das Programm [https://www.mikrocontroller.net/topic/73196#1067153 lboot] (auch im Download-Paket) geschrieben, das unter Linux mit dem schönen Fastboot von Peter Danegger spricht. Damit der Download funktioniert, muss das Pirozeda-Backend (und andere Software, die auf das UART-Interface zugreift) beendet werden. <source lang="shell"> ./bootloader -d /dev/serial0 -b 115200 -t 1024 -p pirozeda_0.2.hex -P aFwUp </source> ===Ohne Bootloader=== siehe [[#Flashen_der_Firmware]] =Einrichten der Optionen= ==HAT-ID== Wie bereits weiter oben geschrieben, ist der HAT-EEProm momentan eher ein Gimmick als wirklich genutztes Feature. Die Anwendung zur Generierung der Daten kann im [https://github.com/raspberrypi/hats/tree/master/eepromutils GitHub-Repo] vom Raspberry Pi heruntergeladen werden. Da der EEProm im normalen Betrieb schreibgeschützt ist, muss SJ1 gebrückt werden - am besten mit einem guten Klecks Lötzinn. Anschließend kann mit dem Script eepflash.sh (liegt dem Download-Paket bei) das EEProm-Image geschrieben werden: <source lang="bash"> sudo ./eepflash.sh -w -f=pirozeda-hat_id.eep -t=24c32 -a=50 </source> Aktuell sind weder Product-ID noch Version-ID vergeben, ansonsten ist die Konfiguration wie folgt: <pre> # Start of atom #0 of type 0x0001 and length 60 # Vendor info product_uuid 9edc3aef-683c-4007-b2f2-3ea4969b1737 product_id 0x0000 product_ver 0x0000 vendor "hobbyelektronik.org" # length=19 product "Pirozeda HAT v0.1" # length=17 # End of atom. CRC16=0x9a75 # Start of atom #1 of type 0x0002 and length 32 # GPIO map info gpio_drive 0 gpio_slew 0 gpio_hysteresis 0 back_power 0 # GPIO FUNCTION PULL # ---- -------- ---- setgpio 22 INPUT UP setgpio 26 OUTPUT NONE </pre> ==RTC== Die [http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-RTC/index.html Netzmafia] hat einen recht guten Artikel, wie man die hwclock bedient. Wer sich nicht einlesen will, hier im Schnelldurchlauf: Testen der RTC: <source lang="shell"> #call bash as superuser, this is needed to get the echo working properly sudo bash modprobe rtc-ds1307 echo "ds1307 0x68" > /sys/class/i2c-adapter/i2c-1/new_device #Auslesen der Uhr hwclock --debug -r exit </source> Dauerhaftes aktivieren der RTC: <source lang="shell"> sudo bash # enable module echo "# enable DS1307-RTC" >> /etc/modules echo "rtc-ds1307" >> /etc/modules # remove fake-hwclock update-rc.d -f fake-hwclock disable update-rc.d -f fake-hwclock remove apt-get remove fake-hwclock # overwrite prepared configuration of hwclock cp /etc/init.d/hwclock.sh ./hwclock.old cat ./hwclock.new > /etc/init.d/hwclock.sh # enable start/stop script update-rc.d hwclock.sh enable exit </source> Laut Anleitung von Netzmafia muss die Datei <code>/etc/init.d/hwclock.sh</code> noch wie folgt angepasst werden: <source lang="text"> Nun muss noch das Start/Stopp-Script für die RTC angepasst werden. Dazu wird (als root-User) die Datei /etc/init.d/hwclock.sh mit dem Editor bearbeitet. Zunächst tragen Sie am Anfang des Scripts die Default-Wert ein bzw. überprüfen diese: # These defaults are user-overridable in /etc/default/hwclock BADYEAR=no HWCLOCKACCESS=yes HWCLOCKPARS=' --noadjfile --utc' HCTOSYS_DEVICE=rtc0 Nach der Zeile 'case "$1" in start)' werden die folgenden drei Zeilen auskommentieren ('#' davorsetzen): #if [ -d /run/udev ] || [ -d /dev/.udev ]; then # return 0 #fi </source> Um das zu vereinfachen, habe ich eine SH-Datei vorbereitet, natürlich muss sich diese (<code>hwclock.new</code>) im gleichen Verzeichnis liegen, damit es funktioniert. Im Ordner <code>options/rtc</code> befindet sich sowohl die <code>rtc-test.sh</code> als auch <code>rtc-enable.sh</code>. Da diese über meinen Windows-PC gewandert sind und dadurch ihre Dateieigenschaften verloren haben, müssen sie entweder als ausführbar markiert werden oder mit <code>/bin/bash</code> gestartet werden: <source lang="shell"> sudo /bin/bash rtc-test.sh </source> ==I²C + Taster== Für die Verwendung des I²C muss eigentlich nur in <code>raspi-config</code> das I²C-Interface aktiviert werden. Mit der Konfiguration im ID-EEPRom wird der Taster in den Device-Tree eingebunden, allerdings kann er prinzipiell auch ohne angesprochen werden. =Backend= Das Back- und Frontend aus [[Pirozeda]] kann prinzipiell weiterverwendet werden. Es gibt allerdings noch keinen Support der neuen Features. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Verbesserungsmöglichkeiten= * Korrektur der Reset-Beschaltung * ESD-Schutz hinzufügen. Aktuell können auf den Footprints von C7, C11 und C14 ESD-Schutzdioden wie B72500D50A60 von Reichelt bestückt werden. Allerdings ist die Positionierung nicht ideal * Stiftwanne für den SPI-Schnittstelle oben auf der Leiterkarte platzieren * Die Widerstände für die Direktverbindung so platzieren, dass sie für das Bootloader-Update einfacher bestückt werden können (oder gleich Jumper) * Hinzufügen der Batteriehalter der billigen RTC-Module (Recycling FTW!) * Entfernen des nicht benötigten I²C-Levelshifters * Vermeiden von Backfeed in der Direkt-Variante =Download= [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format '''Achtung: Bisher nicht verifiziert!''' [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] d9ee7a15a7b3f950ca2d187cdbea5d8954e63aa6 1322 1321 2019-03-21T21:04:36Z Chris 2 /* Bestücken der Leiterkarte */ typo wikitext text/x-wiki Wie bereits im [[Pirozeda|Hauptartikel]] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADMUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar Geschmackssache aber in Hinblick auf Platz das Beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== '''Noch nicht aufgebaut und getestet.''' Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist, dass neben der gemeinsamen Masse mit der Solaranlage Backfeed entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Diese Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== '''Aufgebaut und erfolgreich getestet.''' Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_opto_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_opto_assy.png|Bestückungsplan mit Optokoppler pirozeda_hat_0.1_opto.jpg|Aufgebauter HAT - es passt sogar ein MJ-Quarz </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R13, R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== '''Aufgebaut und weitestgehend erfolgreich getestet.''' Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator pirozeda_hat_0.1_adum.jpg|Aufgebauter HAT mit Hotfix </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 1 || R9 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} Bei der Schaltungsentwicklung hat sich leider ein dummer Fehler eingeschlichen. Ich dachte nicht daran, dass der ADuM !RES treiben wird - und das v.a. nach GND. Kann man zwar halbwegs in Software umgehen, ist aber Mist. '''Die einfachste Fehlerbeseitigung ist, R10 einfach nicht zu bestücken.''' Der ADuM1301 ist trotz des fehlenden Features die günstigste Lösung. Der Reset des Mikrocontrollers (und damit das Wechseln in den Bootloader) kann auch per Kommando ausgelöst werden. Wer will, kann jedoch auch einen Hotfix implementieren: Dazu muss das obere Pad von R10 von der Leiterbahn getrennt werden (rot). Auf den Pads von R18 (rechts) und R10 kann nun ein BSS138 verdreht aufgesetzt werden. Das obere Pad muss dabei noch mit Masse verbunden werden (orange). <gallery> Pirozeda_hat_0.1_adum_hotfix.png Pirozeda_hat_0.1_adum_hotfix.jpg </gallery> Achtung: Auch mit diesem Hotfix gibt es einen Fallstrick: Ist die "Raspberry Pi"-Seite Stromlos, geht der Ausgangspin des ADuM auf high, folglich hängt Reset bei low (aktiv). Kann seine Vorteile haben, zum Flashen des Mikrocontrollers aber eher unpraktisch. =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== '''Aufgebaut und erfolgreich getestet.''' Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEProm ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SJ1 || || SJ || |- | 1 || C6 || 100n || C0603 || X7R-G0603 100N |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 2 || R3, R4 || 3k3 || R0603 || RND 0603 1 3,3K |} Aktuell gibt es noch keine weitere Unterstützung hierfür. Es handelt sich also eher um ein Gimmick. Den EEProm kann man sich recht günstig von eBay-Modulen "abernten" - einfach im nächsten Abschnitt weiterlesen. ==Real-Time-Clock== '''Aufgebaut und erfolgreich getestet.''' Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R11, R12 || 0 || R0603 || RND 0603 1 0 |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 2 || R6, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. Der Levelshifter kann nach ersten Testes getrost weggelassen werden. Wem der DS1307 bei Reichelt zu teuer ist, kann sich bei eBay ein Modul mit dem Chip, passendem Quarz (der zufällig dem verwendeten entspricht) und einem ebenfalls passenden EEProm besorgen. Der Batteriehalter passt im aktuellen Design leider nicht. <gallery> EBay-RTC-Module.jpg|RTC-Modul als Bauteilspender </gallery> ==Option: I²C(-OLED) + Taster== '''Noch nicht aufgebaut und getestet.''' Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |} ==Status-LEDs== '''Aufgebaut und erfolgreich getestet.''' Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 3 || R24, R25, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || LED1 || gn || CHIP-LED0603 || |- | 2 || LED2, LED3 || or || CHIP-LED0603 || |} LED1 (mitte) zeigt Aktivität an, LED2 (unten) ist mehr oder weniger die Power-LED. Mehr oder weniger, da sie beim Start der Firmware aktiviert wird (nicht aber im Bootloader). Dadurch kann man sehr schnell erkennen, ob sich die Hardware in einem Bootloop befindet. LED3 (oben) kann vom Raspberry Pi angesteuert werden. Standardmäßig sind in der <code>config.h</code> folgende Zeiten für LED1 eingestellt: * Start der Anwendung: 250 ms * Korrekt empfangene Nachrichten: 10 ms * Fehlerhaft empfangene Nachrichten: 200 ms Damit kann man auf den einen Blick erkennen, ob Daten vernünftig ankommen und verarbeitet werden können. =Aufbau der Hardware= ==Bestücken der Leiterkarte== Die Hardware kann im Prinzip in beliebiger Reihenfolge aufgebaut werden. Trotzdem ist es ratsam, die großen/hohen Bauteile zuletzt aufzulöten. Die Steckkräfte einer 2x20 Buchsenleiste sind vergleichsweise groß. Diese können reduziert werden, indem nicht verwendete Pins aus der Buchsenleiste entfernt werden. Um diese nicht wieder (fragt nicht) zurückstecken zu müssen, hier eine Auflistung der benötigten Pins: 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 15, 17, 20, 25, 27, 28, 30, 34, 37, 39. Oder einfach als Bild: <gallery> Pirozeda_hat_0.1_buchsenleiste_pins.png|benötigte Pins (blau markiert) </gallery> Der Wannenstecker lässt sich am einfachsten auflöten, wenn man die Pads auf einer Seite (egal welche) der Leiterkarte bisschen stärker verzinnt. Dadurch kann man den Konnektor ein wenig verklemmen und vor dem Verlöten besser ausrichten. ==Zuleitung== Als Zuleitung habe ich für die ersten Muster den Artikel LIYY 614 (Steuerleitung 6x0,14mm², ungeschirmt) von Reichelt verwendet. Beim Bestellen habe ich leider mehr auf den Preis als die Schirmung geachtet. In Hinblick darauf, dass der Schirm der Buchse im Regler eh nicht mit Masse verbunden ist, ist es eine ziemliche Fummelarbeit, diese mit dem Massepin zu verbinden. Erkenntnisse über die maximale Leitungslänge gibt es noch nicht. Der Vorteil dieser Leitung ist: die Adern können direkt im Pfostenverbinder verpresst werden: <gallery> Pirozeda_hat_0.1_pfosten.jpg </gallery> Ich habe mich für folgende Farbgebung entschieden, beim Pinmapping selbst gibt es keine Wahl: {| class="wikitable" ! Mini-DIN || Signal || Farbe || Wannenstecker |- | 3 || MISO || grau || 1 |- | 4 || GND || braun || 3 |- | 5 || 3V3 || rosa || 5 |- | 6 || MOSI || grün || 2 |- | 7 || SCK || gelb || 4 |- | 8 || !CS || weiß || 6 |} Beim Mini-DIN-Stecker sollte darauf geachtet werden, die äußere Hülle nicht komplett über den Rest zu stülpen, da die Buchse beim Regler ziemlich weit nach innen versetzt ist: <gallery> Pirozeda_hat_0.1_minidin.jpg </gallery> =Firmware= Grundsätzlich läuft die Firmware des Originaldesign auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel und viele neue Features fehlen: Ab 0.2: * Status-LEDs * Uptime-Counter * Messung der Versorgungsspannung * Anzeigen von Bootinformationen ** Resetgrund ** Anzahl der vorherigen Reboots ** Dauer der vorherigen Uptime ** Fusecheck ** Watchdog-Info ** Aktivierte Nachrichten * Neustart + Wechsel in den Bootloader per Kommando * Statistik über empfangene Nachrichten (optional) * Timestamps (optional, aktuell nicht kompatibel mit der Backend-Software) * Erneutes übertragen der Headerinformationen * Kann die Firmware bei einem "Katzen-Paket" miauen. Einfach nur weil. ==Konfiguration== Einige der Features müssen vor dem Kompilieren aktiviert bzw. eingestellt werden. Die Schalter und Defines hierfür befinden sich in zwei Header-Dateien: <code>config.h</code> * <code>PIROZEDA_KITTY_DEBUG</code>: Anzeigen der "Katzen-Pakete" (Vorgabe: inaktiv) * <code>PIROZEDA_TIMESTAMPS</code>: Anzeigen der Timestamps (Vorgabe: inaktiv) * <code>PIROZEDA_WDT_TIMEOUT</code>: Timeout des Watchdogs (Vorgabe: 4 s) * <code>PIROZEDA_UPTIME</code>: Führen der Uptime, abrufbar über den Befehl (Vorgabe: aktiv) * <code>PIROZEDA_SUPPLY_AVGCNT</code>: Anzahl der Messwerte für die Mittelwertbildung der Systemspannung (Vorgabe: 10, maximal: 32) * <code>PIROZEDA_HEADERCNT</code>: Anzahl der Kopfzeilen-Datensätze, die nach dem Start oder Befehl <code>header</code> angezeigt werden (Vorgabe: 200, maximal: 255) * <code>PIROZEDA_STATUS_LED_BOOT</code>: Leuchtdauer der Status-LED nach dem Start (Vorgabe: 100 -> 250 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXOK</code>: Leuchtdauer der Status-LED bei empfangenem Paket (Vorgabe: 4 -> 10 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXERR</code>: Leuchtdauer der Status-LED bei einem Fehler (Vorgabe: 80 -> 200 ms, maximal: 255) * <code>BOOTLOADER_PASSWORD</code>: "Passwort" zum Wechsel in den Bootloader (Vorgabe: "FwUp", maximal 4 Zeichen, darf keine Teilstrings von Befehlen enthalten) <code>prozeda_cfg.h</code> * <code>PROZEDA_USE_COLUMN_NAMES</code>: Verwenden der Spaltennamen (irrelevant für Pirozeda) * <code>PROZEDA_SUPPORT_DISPLAY</code>: Aktiviert den Empfang von Displaydaten (Vorgabe: aktiv) * <code>PROZEDA_SUPPORT_HEADER</code>: Aktiviert den Empfang von Kopfzeilen-Datensätzen (Vorgabe: aktiv) * <code>PROZEDA_IGNORE_KITTY</code>: Ignorieren von Katzen-Paketen, andernfalls werden Fehler ausgegeben (Vorgabe: aktiv) * <code>PROZEDA_MSG_MAXTICKS</code>: Ticks, nach denen ein Paket als abgeschlossen erkannt wird, sollte nur bei Anpassung der CPU-Frequenz angepasst werden (Vorgabe: 3) ==Befehle== Neu ist ab v0.2, dass Befehle an den Mikrocontroller gesendet werden können. Je nach Konfiguration sind dies: * <code>reset</code>: Neustart * <code>uptime</code>: Anzeige der Laufzeit * <code>bootinfo</code>: Anzeigen der Infos, die auch beim (Neu-)Start angezeigt werden * <code>header</code>: Header werden gemäß <code>PIROZEDA_HEADERCNT</code> erneut ausgegeben * <code>stats</code>: Anzeigen der Statistik über empfangene Nachrichten und Empfangsfehler Alle Befehle sind Case-sensitive. ==Flashen der Firmware== Mit den Möglichkeiten steigt die Komplexität. Dadurch dass der die Hardware für die Verwendung mit und ohne Bootloader ausgelegt ist, gibt es mehrere "Pfade" für das Flashen. Wer auf Nummer sicher gehen will, lädt einfach Bootloader und Firmware auf den Mikrocontroller herunter. Selbst wenn man "nur" die Variante mit unidirektionalem UART hat - die Brücken Versorgung und für den UART zum Mikrocontroller ist schneller gelötet als die Stiftleiste für den ISP-Port. Das Einlöten einer wahnsinnig hohen Stiftleiste kann übrigens umgangen werden, indem eine Stiftleiste in das Programmierkabel gesteckt und im Footprint der Buchse "verkeilt" wird. Wirklich keine Dauerlösung aber im Idealfall muss man es nur einmal machen. ===Über Raspberry Pi=== Zunächst muss, wenn nicht schon geschehen, über <code>sudo raspi-config</code> das SPI-Interface aktiviert (reboot nicht vergessen) und [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer#Installation_der_Compiler AVRDUDE installiert] werden. Den Regler vom HAT trennen, nicht vergessen, dass R10 oder der Hotfix entfernt werden muss, falls der ADuM-Isolator verwendet und einseitig versorgt (also nicht auf dem Raspi steckt) wird und anschließend den SPI-Port mit SV2 verbinden. {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin |- | MISO || 1 || BCM 9 || 21 |- | 3V3 || 2 || 3V3 || 17 |- | SCK || 3 || BCM 11 || 23 |- | MOSI || 4 || BCM 10 || 19 |- | !RES || 5 || BCM 25 || 22 |- | GND || 6 || GND || 20 |} ====Mit Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = FC }} Die empfohlene Variante (auch wenn man nicht beabsichtigt, den Bootloader zu nutzen). Mit Bootloader sind das folgende Befehle: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0xFC:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_fboot_0.2.hex" </source> ====Ohne Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} 'cause I ain't gonna judge you <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_0.2.hex" </source> ==Update der Firmware== In Sachen Bootloader bin ich ein großer Fan von [https://www.mikrocontroller.net/articles/AVR_Bootloader_FastBoot_von_Peter_Dannegger Peter Danneggers Fastboot]. Er ist klein, schnell und zuverlässig. Um einen kleinen Unterschied zu machen, lautet das Passwort zum Starten nicht "Peda" sondern "FwUp", was ein kleines Problem mit sich bringt. "Peda" ist nicht nur der Spitzname vom Autor, das "a" wird zur automatischen Baudratenerkennung verwendet. Das von mir gewählte Passwort hat das nicht zu bieten. Was mir bei der Verwendung von [https://luani.de/projekte/updateloader/ UpdateLoader] aufgefallen ist: es funktioniert trotzdem. Ganz einfach, weil der Autor ein "a" voranstellt. Das funktioniert dann auch mit so gut wie allen anderen Download-Tools. ===Mit Bootloader=== Das Firmware-Update funktioniert nur bei bidirektionaler UART-Kommunikation mit dem Mikrocontroller, also bei der Variante Direkt und ADuM-Isolator. Wenn man mutig ist, kann man bei der Optokoppler-Variante R19 und R27 bestückt werden. In jedem Fall muss die Mikrocontroller-Seite mit Strom versorgt werden, also am einfachsten am Solarregler angeschlossen lassen. Berhard M. (boregard) hat das Programm [https://www.mikrocontroller.net/topic/73196#1067153 lboot] (auch im Download-Paket) geschrieben, das unter Linux mit dem schönen Fastboot von Peter Danegger spricht. Damit der Download funktioniert, muss das Pirozeda-Backend (und andere Software, die auf das UART-Interface zugreift) beendet werden. <source lang="shell"> ./bootloader -d /dev/serial0 -b 115200 -t 1024 -p pirozeda_0.2.hex -P aFwUp </source> ===Ohne Bootloader=== siehe [[#Flashen_der_Firmware]] =Einrichten der Optionen= ==HAT-ID== Wie bereits weiter oben geschrieben, ist der HAT-EEProm momentan eher ein Gimmick als wirklich genutztes Feature. Die Anwendung zur Generierung der Daten kann im [https://github.com/raspberrypi/hats/tree/master/eepromutils GitHub-Repo] vom Raspberry Pi heruntergeladen werden. Da der EEProm im normalen Betrieb schreibgeschützt ist, muss SJ1 gebrückt werden - am besten mit einem guten Klecks Lötzinn. Anschließend kann mit dem Script eepflash.sh (liegt dem Download-Paket bei) das EEProm-Image geschrieben werden: <source lang="bash"> sudo ./eepflash.sh -w -f=pirozeda-hat_id.eep -t=24c32 -a=50 </source> Aktuell sind weder Product-ID noch Version-ID vergeben, ansonsten ist die Konfiguration wie folgt: <pre> # Start of atom #0 of type 0x0001 and length 60 # Vendor info product_uuid 9edc3aef-683c-4007-b2f2-3ea4969b1737 product_id 0x0000 product_ver 0x0000 vendor "hobbyelektronik.org" # length=19 product "Pirozeda HAT v0.1" # length=17 # End of atom. CRC16=0x9a75 # Start of atom #1 of type 0x0002 and length 32 # GPIO map info gpio_drive 0 gpio_slew 0 gpio_hysteresis 0 back_power 0 # GPIO FUNCTION PULL # ---- -------- ---- setgpio 22 INPUT UP setgpio 26 OUTPUT NONE </pre> ==RTC== Die [http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-RTC/index.html Netzmafia] hat einen recht guten Artikel, wie man die hwclock bedient. Wer sich nicht einlesen will, hier im Schnelldurchlauf: Testen der RTC: <source lang="shell"> #call bash as superuser, this is needed to get the echo working properly sudo bash modprobe rtc-ds1307 echo "ds1307 0x68" > /sys/class/i2c-adapter/i2c-1/new_device #Auslesen der Uhr hwclock --debug -r exit </source> Dauerhaftes aktivieren der RTC: <source lang="shell"> sudo bash # enable module echo "# enable DS1307-RTC" >> /etc/modules echo "rtc-ds1307" >> /etc/modules # remove fake-hwclock update-rc.d -f fake-hwclock disable update-rc.d -f fake-hwclock remove apt-get remove fake-hwclock # overwrite prepared configuration of hwclock cp /etc/init.d/hwclock.sh ./hwclock.old cat ./hwclock.new > /etc/init.d/hwclock.sh # enable start/stop script update-rc.d hwclock.sh enable exit </source> Laut Anleitung von Netzmafia muss die Datei <code>/etc/init.d/hwclock.sh</code> noch wie folgt angepasst werden: <source lang="text"> Nun muss noch das Start/Stopp-Script für die RTC angepasst werden. Dazu wird (als root-User) die Datei /etc/init.d/hwclock.sh mit dem Editor bearbeitet. Zunächst tragen Sie am Anfang des Scripts die Default-Wert ein bzw. überprüfen diese: # These defaults are user-overridable in /etc/default/hwclock BADYEAR=no HWCLOCKACCESS=yes HWCLOCKPARS=' --noadjfile --utc' HCTOSYS_DEVICE=rtc0 Nach der Zeile 'case "$1" in start)' werden die folgenden drei Zeilen auskommentieren ('#' davorsetzen): #if [ -d /run/udev ] || [ -d /dev/.udev ]; then # return 0 #fi </source> Um das zu vereinfachen, habe ich eine SH-Datei vorbereitet, natürlich muss sich diese (<code>hwclock.new</code>) im gleichen Verzeichnis liegen, damit es funktioniert. Im Ordner <code>options/rtc</code> befindet sich sowohl die <code>rtc-test.sh</code> als auch <code>rtc-enable.sh</code>. Da diese über meinen Windows-PC gewandert sind und dadurch ihre Dateieigenschaften verloren haben, müssen sie entweder als ausführbar markiert werden oder mit <code>/bin/bash</code> gestartet werden: <source lang="shell"> sudo /bin/bash rtc-test.sh </source> ==I²C + Taster== Für die Verwendung des I²C muss eigentlich nur in <code>raspi-config</code> das I²C-Interface aktiviert werden. Mit der Konfiguration im ID-EEPRom wird der Taster in den Device-Tree eingebunden, allerdings kann er prinzipiell auch ohne angesprochen werden. =Backend= Das Back- und Frontend aus [[Pirozeda]] kann prinzipiell weiterverwendet werden. Es gibt allerdings noch keinen Support der neuen Features. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Verbesserungsmöglichkeiten= * Korrektur der Reset-Beschaltung * ESD-Schutz hinzufügen. Aktuell können auf den Footprints von C7, C11 und C14 ESD-Schutzdioden wie B72500D50A60 von Reichelt bestückt werden. Allerdings ist die Positionierung nicht ideal * Stiftwanne für den SPI-Schnittstelle oben auf der Leiterkarte platzieren * Die Widerstände für die Direktverbindung so platzieren, dass sie für das Bootloader-Update einfacher bestückt werden können (oder gleich Jumper) * Hinzufügen der Batteriehalter der billigen RTC-Module (Recycling FTW!) * Entfernen des nicht benötigten I²C-Levelshifters * Vermeiden von Backfeed in der Direkt-Variante =Download= [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format '''Achtung: Bisher nicht verifiziert!''' [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] c40d0a657efc256f59cdd74d43b543fdfc61eafe 1324 1322 2019-03-21T21:07:24Z Chris 2 /* Download */ wikitext text/x-wiki Wie bereits im [[Pirozeda|Hauptartikel]] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADMUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar Geschmackssache aber in Hinblick auf Platz das Beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== '''Noch nicht aufgebaut und getestet.''' Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist, dass neben der gemeinsamen Masse mit der Solaranlage Backfeed entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Diese Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== '''Aufgebaut und erfolgreich getestet.''' Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_opto_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_opto_assy.png|Bestückungsplan mit Optokoppler pirozeda_hat_0.1_opto.jpg|Aufgebauter HAT - es passt sogar ein MJ-Quarz </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R13, R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== '''Aufgebaut und weitestgehend erfolgreich getestet.''' Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator pirozeda_hat_0.1_adum.jpg|Aufgebauter HAT mit Hotfix </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 1 || R9 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} Bei der Schaltungsentwicklung hat sich leider ein dummer Fehler eingeschlichen. Ich dachte nicht daran, dass der ADuM !RES treiben wird - und das v.a. nach GND. Kann man zwar halbwegs in Software umgehen, ist aber Mist. '''Die einfachste Fehlerbeseitigung ist, R10 einfach nicht zu bestücken.''' Der ADuM1301 ist trotz des fehlenden Features die günstigste Lösung. Der Reset des Mikrocontrollers (und damit das Wechseln in den Bootloader) kann auch per Kommando ausgelöst werden. Wer will, kann jedoch auch einen Hotfix implementieren: Dazu muss das obere Pad von R10 von der Leiterbahn getrennt werden (rot). Auf den Pads von R18 (rechts) und R10 kann nun ein BSS138 verdreht aufgesetzt werden. Das obere Pad muss dabei noch mit Masse verbunden werden (orange). <gallery> Pirozeda_hat_0.1_adum_hotfix.png Pirozeda_hat_0.1_adum_hotfix.jpg </gallery> Achtung: Auch mit diesem Hotfix gibt es einen Fallstrick: Ist die "Raspberry Pi"-Seite Stromlos, geht der Ausgangspin des ADuM auf high, folglich hängt Reset bei low (aktiv). Kann seine Vorteile haben, zum Flashen des Mikrocontrollers aber eher unpraktisch. =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== '''Aufgebaut und erfolgreich getestet.''' Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEProm ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SJ1 || || SJ || |- | 1 || C6 || 100n || C0603 || X7R-G0603 100N |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 2 || R3, R4 || 3k3 || R0603 || RND 0603 1 3,3K |} Aktuell gibt es noch keine weitere Unterstützung hierfür. Es handelt sich also eher um ein Gimmick. Den EEProm kann man sich recht günstig von eBay-Modulen "abernten" - einfach im nächsten Abschnitt weiterlesen. ==Real-Time-Clock== '''Aufgebaut und erfolgreich getestet.''' Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R11, R12 || 0 || R0603 || RND 0603 1 0 |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 2 || R6, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. Der Levelshifter kann nach ersten Testes getrost weggelassen werden. Wem der DS1307 bei Reichelt zu teuer ist, kann sich bei eBay ein Modul mit dem Chip, passendem Quarz (der zufällig dem verwendeten entspricht) und einem ebenfalls passenden EEProm besorgen. Der Batteriehalter passt im aktuellen Design leider nicht. <gallery> EBay-RTC-Module.jpg|RTC-Modul als Bauteilspender </gallery> ==Option: I²C(-OLED) + Taster== '''Noch nicht aufgebaut und getestet.''' Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |} ==Status-LEDs== '''Aufgebaut und erfolgreich getestet.''' Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 3 || R24, R25, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || LED1 || gn || CHIP-LED0603 || |- | 2 || LED2, LED3 || or || CHIP-LED0603 || |} LED1 (mitte) zeigt Aktivität an, LED2 (unten) ist mehr oder weniger die Power-LED. Mehr oder weniger, da sie beim Start der Firmware aktiviert wird (nicht aber im Bootloader). Dadurch kann man sehr schnell erkennen, ob sich die Hardware in einem Bootloop befindet. LED3 (oben) kann vom Raspberry Pi angesteuert werden. Standardmäßig sind in der <code>config.h</code> folgende Zeiten für LED1 eingestellt: * Start der Anwendung: 250 ms * Korrekt empfangene Nachrichten: 10 ms * Fehlerhaft empfangene Nachrichten: 200 ms Damit kann man auf den einen Blick erkennen, ob Daten vernünftig ankommen und verarbeitet werden können. =Aufbau der Hardware= ==Bestücken der Leiterkarte== Die Hardware kann im Prinzip in beliebiger Reihenfolge aufgebaut werden. Trotzdem ist es ratsam, die großen/hohen Bauteile zuletzt aufzulöten. Die Steckkräfte einer 2x20 Buchsenleiste sind vergleichsweise groß. Diese können reduziert werden, indem nicht verwendete Pins aus der Buchsenleiste entfernt werden. Um diese nicht wieder (fragt nicht) zurückstecken zu müssen, hier eine Auflistung der benötigten Pins: 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 15, 17, 20, 25, 27, 28, 30, 34, 37, 39. Oder einfach als Bild: <gallery> Pirozeda_hat_0.1_buchsenleiste_pins.png|benötigte Pins (blau markiert) </gallery> Der Wannenstecker lässt sich am einfachsten auflöten, wenn man die Pads auf einer Seite (egal welche) der Leiterkarte bisschen stärker verzinnt. Dadurch kann man den Konnektor ein wenig verklemmen und vor dem Verlöten besser ausrichten. ==Zuleitung== Als Zuleitung habe ich für die ersten Muster den Artikel LIYY 614 (Steuerleitung 6x0,14mm², ungeschirmt) von Reichelt verwendet. Beim Bestellen habe ich leider mehr auf den Preis als die Schirmung geachtet. In Hinblick darauf, dass der Schirm der Buchse im Regler eh nicht mit Masse verbunden ist, ist es eine ziemliche Fummelarbeit, diese mit dem Massepin zu verbinden. Erkenntnisse über die maximale Leitungslänge gibt es noch nicht. Der Vorteil dieser Leitung ist: die Adern können direkt im Pfostenverbinder verpresst werden: <gallery> Pirozeda_hat_0.1_pfosten.jpg </gallery> Ich habe mich für folgende Farbgebung entschieden, beim Pinmapping selbst gibt es keine Wahl: {| class="wikitable" ! Mini-DIN || Signal || Farbe || Wannenstecker |- | 3 || MISO || grau || 1 |- | 4 || GND || braun || 3 |- | 5 || 3V3 || rosa || 5 |- | 6 || MOSI || grün || 2 |- | 7 || SCK || gelb || 4 |- | 8 || !CS || weiß || 6 |} Beim Mini-DIN-Stecker sollte darauf geachtet werden, die äußere Hülle nicht komplett über den Rest zu stülpen, da die Buchse beim Regler ziemlich weit nach innen versetzt ist: <gallery> Pirozeda_hat_0.1_minidin.jpg </gallery> =Firmware= Grundsätzlich läuft die Firmware des Originaldesign auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel und viele neue Features fehlen: Ab 0.2: * Status-LEDs * Uptime-Counter * Messung der Versorgungsspannung * Anzeigen von Bootinformationen ** Resetgrund ** Anzahl der vorherigen Reboots ** Dauer der vorherigen Uptime ** Fusecheck ** Watchdog-Info ** Aktivierte Nachrichten * Neustart + Wechsel in den Bootloader per Kommando * Statistik über empfangene Nachrichten (optional) * Timestamps (optional, aktuell nicht kompatibel mit der Backend-Software) * Erneutes übertragen der Headerinformationen * Kann die Firmware bei einem "Katzen-Paket" miauen. Einfach nur weil. ==Konfiguration== Einige der Features müssen vor dem Kompilieren aktiviert bzw. eingestellt werden. Die Schalter und Defines hierfür befinden sich in zwei Header-Dateien: <code>config.h</code> * <code>PIROZEDA_KITTY_DEBUG</code>: Anzeigen der "Katzen-Pakete" (Vorgabe: inaktiv) * <code>PIROZEDA_TIMESTAMPS</code>: Anzeigen der Timestamps (Vorgabe: inaktiv) * <code>PIROZEDA_WDT_TIMEOUT</code>: Timeout des Watchdogs (Vorgabe: 4 s) * <code>PIROZEDA_UPTIME</code>: Führen der Uptime, abrufbar über den Befehl (Vorgabe: aktiv) * <code>PIROZEDA_SUPPLY_AVGCNT</code>: Anzahl der Messwerte für die Mittelwertbildung der Systemspannung (Vorgabe: 10, maximal: 32) * <code>PIROZEDA_HEADERCNT</code>: Anzahl der Kopfzeilen-Datensätze, die nach dem Start oder Befehl <code>header</code> angezeigt werden (Vorgabe: 200, maximal: 255) * <code>PIROZEDA_STATUS_LED_BOOT</code>: Leuchtdauer der Status-LED nach dem Start (Vorgabe: 100 -> 250 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXOK</code>: Leuchtdauer der Status-LED bei empfangenem Paket (Vorgabe: 4 -> 10 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXERR</code>: Leuchtdauer der Status-LED bei einem Fehler (Vorgabe: 80 -> 200 ms, maximal: 255) * <code>BOOTLOADER_PASSWORD</code>: "Passwort" zum Wechsel in den Bootloader (Vorgabe: "FwUp", maximal 4 Zeichen, darf keine Teilstrings von Befehlen enthalten) <code>prozeda_cfg.h</code> * <code>PROZEDA_USE_COLUMN_NAMES</code>: Verwenden der Spaltennamen (irrelevant für Pirozeda) * <code>PROZEDA_SUPPORT_DISPLAY</code>: Aktiviert den Empfang von Displaydaten (Vorgabe: aktiv) * <code>PROZEDA_SUPPORT_HEADER</code>: Aktiviert den Empfang von Kopfzeilen-Datensätzen (Vorgabe: aktiv) * <code>PROZEDA_IGNORE_KITTY</code>: Ignorieren von Katzen-Paketen, andernfalls werden Fehler ausgegeben (Vorgabe: aktiv) * <code>PROZEDA_MSG_MAXTICKS</code>: Ticks, nach denen ein Paket als abgeschlossen erkannt wird, sollte nur bei Anpassung der CPU-Frequenz angepasst werden (Vorgabe: 3) ==Befehle== Neu ist ab v0.2, dass Befehle an den Mikrocontroller gesendet werden können. Je nach Konfiguration sind dies: * <code>reset</code>: Neustart * <code>uptime</code>: Anzeige der Laufzeit * <code>bootinfo</code>: Anzeigen der Infos, die auch beim (Neu-)Start angezeigt werden * <code>header</code>: Header werden gemäß <code>PIROZEDA_HEADERCNT</code> erneut ausgegeben * <code>stats</code>: Anzeigen der Statistik über empfangene Nachrichten und Empfangsfehler Alle Befehle sind Case-sensitive. ==Flashen der Firmware== Mit den Möglichkeiten steigt die Komplexität. Dadurch dass der die Hardware für die Verwendung mit und ohne Bootloader ausgelegt ist, gibt es mehrere "Pfade" für das Flashen. Wer auf Nummer sicher gehen will, lädt einfach Bootloader und Firmware auf den Mikrocontroller herunter. Selbst wenn man "nur" die Variante mit unidirektionalem UART hat - die Brücken Versorgung und für den UART zum Mikrocontroller ist schneller gelötet als die Stiftleiste für den ISP-Port. Das Einlöten einer wahnsinnig hohen Stiftleiste kann übrigens umgangen werden, indem eine Stiftleiste in das Programmierkabel gesteckt und im Footprint der Buchse "verkeilt" wird. Wirklich keine Dauerlösung aber im Idealfall muss man es nur einmal machen. ===Über Raspberry Pi=== Zunächst muss, wenn nicht schon geschehen, über <code>sudo raspi-config</code> das SPI-Interface aktiviert (reboot nicht vergessen) und [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer#Installation_der_Compiler AVRDUDE installiert] werden. Den Regler vom HAT trennen, nicht vergessen, dass R10 oder der Hotfix entfernt werden muss, falls der ADuM-Isolator verwendet und einseitig versorgt (also nicht auf dem Raspi steckt) wird und anschließend den SPI-Port mit SV2 verbinden. {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin |- | MISO || 1 || BCM 9 || 21 |- | 3V3 || 2 || 3V3 || 17 |- | SCK || 3 || BCM 11 || 23 |- | MOSI || 4 || BCM 10 || 19 |- | !RES || 5 || BCM 25 || 22 |- | GND || 6 || GND || 20 |} ====Mit Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = FC }} Die empfohlene Variante (auch wenn man nicht beabsichtigt, den Bootloader zu nutzen). Mit Bootloader sind das folgende Befehle: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0xFC:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_fboot_0.2.hex" </source> ====Ohne Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} 'cause I ain't gonna judge you <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_0.2.hex" </source> ==Update der Firmware== In Sachen Bootloader bin ich ein großer Fan von [https://www.mikrocontroller.net/articles/AVR_Bootloader_FastBoot_von_Peter_Dannegger Peter Danneggers Fastboot]. Er ist klein, schnell und zuverlässig. Um einen kleinen Unterschied zu machen, lautet das Passwort zum Starten nicht "Peda" sondern "FwUp", was ein kleines Problem mit sich bringt. "Peda" ist nicht nur der Spitzname vom Autor, das "a" wird zur automatischen Baudratenerkennung verwendet. Das von mir gewählte Passwort hat das nicht zu bieten. Was mir bei der Verwendung von [https://luani.de/projekte/updateloader/ UpdateLoader] aufgefallen ist: es funktioniert trotzdem. Ganz einfach, weil der Autor ein "a" voranstellt. Das funktioniert dann auch mit so gut wie allen anderen Download-Tools. ===Mit Bootloader=== Das Firmware-Update funktioniert nur bei bidirektionaler UART-Kommunikation mit dem Mikrocontroller, also bei der Variante Direkt und ADuM-Isolator. Wenn man mutig ist, kann man bei der Optokoppler-Variante R19 und R27 bestückt werden. In jedem Fall muss die Mikrocontroller-Seite mit Strom versorgt werden, also am einfachsten am Solarregler angeschlossen lassen. Berhard M. (boregard) hat das Programm [https://www.mikrocontroller.net/topic/73196#1067153 lboot] (auch im Download-Paket) geschrieben, das unter Linux mit dem schönen Fastboot von Peter Danegger spricht. Damit der Download funktioniert, muss das Pirozeda-Backend (und andere Software, die auf das UART-Interface zugreift) beendet werden. <source lang="shell"> ./bootloader -d /dev/serial0 -b 115200 -t 1024 -p pirozeda_0.2.hex -P aFwUp </source> ===Ohne Bootloader=== siehe [[#Flashen_der_Firmware]] =Einrichten der Optionen= ==HAT-ID== Wie bereits weiter oben geschrieben, ist der HAT-EEProm momentan eher ein Gimmick als wirklich genutztes Feature. Die Anwendung zur Generierung der Daten kann im [https://github.com/raspberrypi/hats/tree/master/eepromutils GitHub-Repo] vom Raspberry Pi heruntergeladen werden. Da der EEProm im normalen Betrieb schreibgeschützt ist, muss SJ1 gebrückt werden - am besten mit einem guten Klecks Lötzinn. Anschließend kann mit dem Script eepflash.sh (liegt dem Download-Paket bei) das EEProm-Image geschrieben werden: <source lang="bash"> sudo ./eepflash.sh -w -f=pirozeda-hat_id.eep -t=24c32 -a=50 </source> Aktuell sind weder Product-ID noch Version-ID vergeben, ansonsten ist die Konfiguration wie folgt: <pre> # Start of atom #0 of type 0x0001 and length 60 # Vendor info product_uuid 9edc3aef-683c-4007-b2f2-3ea4969b1737 product_id 0x0000 product_ver 0x0000 vendor "hobbyelektronik.org" # length=19 product "Pirozeda HAT v0.1" # length=17 # End of atom. CRC16=0x9a75 # Start of atom #1 of type 0x0002 and length 32 # GPIO map info gpio_drive 0 gpio_slew 0 gpio_hysteresis 0 back_power 0 # GPIO FUNCTION PULL # ---- -------- ---- setgpio 22 INPUT UP setgpio 26 OUTPUT NONE </pre> ==RTC== Die [http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-RTC/index.html Netzmafia] hat einen recht guten Artikel, wie man die hwclock bedient. Wer sich nicht einlesen will, hier im Schnelldurchlauf: Testen der RTC: <source lang="shell"> #call bash as superuser, this is needed to get the echo working properly sudo bash modprobe rtc-ds1307 echo "ds1307 0x68" > /sys/class/i2c-adapter/i2c-1/new_device #Auslesen der Uhr hwclock --debug -r exit </source> Dauerhaftes aktivieren der RTC: <source lang="shell"> sudo bash # enable module echo "# enable DS1307-RTC" >> /etc/modules echo "rtc-ds1307" >> /etc/modules # remove fake-hwclock update-rc.d -f fake-hwclock disable update-rc.d -f fake-hwclock remove apt-get remove fake-hwclock # overwrite prepared configuration of hwclock cp /etc/init.d/hwclock.sh ./hwclock.old cat ./hwclock.new > /etc/init.d/hwclock.sh # enable start/stop script update-rc.d hwclock.sh enable exit </source> Laut Anleitung von Netzmafia muss die Datei <code>/etc/init.d/hwclock.sh</code> noch wie folgt angepasst werden: <source lang="text"> Nun muss noch das Start/Stopp-Script für die RTC angepasst werden. Dazu wird (als root-User) die Datei /etc/init.d/hwclock.sh mit dem Editor bearbeitet. Zunächst tragen Sie am Anfang des Scripts die Default-Wert ein bzw. überprüfen diese: # These defaults are user-overridable in /etc/default/hwclock BADYEAR=no HWCLOCKACCESS=yes HWCLOCKPARS=' --noadjfile --utc' HCTOSYS_DEVICE=rtc0 Nach der Zeile 'case "$1" in start)' werden die folgenden drei Zeilen auskommentieren ('#' davorsetzen): #if [ -d /run/udev ] || [ -d /dev/.udev ]; then # return 0 #fi </source> Um das zu vereinfachen, habe ich eine SH-Datei vorbereitet, natürlich muss sich diese (<code>hwclock.new</code>) im gleichen Verzeichnis liegen, damit es funktioniert. Im Ordner <code>options/rtc</code> befindet sich sowohl die <code>rtc-test.sh</code> als auch <code>rtc-enable.sh</code>. Da diese über meinen Windows-PC gewandert sind und dadurch ihre Dateieigenschaften verloren haben, müssen sie entweder als ausführbar markiert werden oder mit <code>/bin/bash</code> gestartet werden: <source lang="shell"> sudo /bin/bash rtc-test.sh </source> ==I²C + Taster== Für die Verwendung des I²C muss eigentlich nur in <code>raspi-config</code> das I²C-Interface aktiviert werden. Mit der Konfiguration im ID-EEPRom wird der Taster in den Device-Tree eingebunden, allerdings kann er prinzipiell auch ohne angesprochen werden. =Backend= Das Back- und Frontend aus [[Pirozeda]] kann prinzipiell weiterverwendet werden. Es gibt allerdings noch keinen Support der neuen Features. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Verbesserungsmöglichkeiten= * Korrektur der Reset-Beschaltung * ESD-Schutz hinzufügen. Aktuell können auf den Footprints von C7, C11 und C14 ESD-Schutzdioden wie B72500D50A60 von Reichelt bestückt werden. Allerdings ist die Positionierung nicht ideal * Stiftwanne für den SPI-Schnittstelle oben auf der Leiterkarte platzieren * Die Widerstände für die Direktverbindung so platzieren, dass sie für das Bootloader-Update einfacher bestückt werden können (oder gleich Jumper) * Hinzufügen der Batteriehalter der billigen RTC-Module (Recycling FTW!) * Entfernen des nicht benötigten I²C-Levelshifters * Vermeiden von Backfeed in der Direkt-Variante =Download= [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format * Quellen des Bootloaders von Peter Dannegger * Quellen der Firmware + flashbare Images * Scripts für die Einrichtung der Optionen [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] c6aaec9b677f50c7c5ca757281e13b35f746c762 1327 1324 2019-03-21T21:10:39Z Chris 2 Typo korrigiert wikitext text/x-wiki Wie bereits im [[Pirozeda|Hauptartikel]] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar Geschmackssache aber in Hinblick auf Platz das Beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== '''Noch nicht aufgebaut und getestet.''' Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist, dass neben der gemeinsamen Masse mit der Solaranlage Backfeed entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Diese Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== '''Aufgebaut und erfolgreich getestet.''' Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_opto_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_opto_assy.png|Bestückungsplan mit Optokoppler pirozeda_hat_0.1_opto.jpg|Aufgebauter HAT - es passt sogar ein MJ-Quarz </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R13, R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== '''Aufgebaut und weitestgehend erfolgreich getestet.''' Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator pirozeda_hat_0.1_adum.jpg|Aufgebauter HAT mit Hotfix </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 1 || R9 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} Bei der Schaltungsentwicklung hat sich leider ein dummer Fehler eingeschlichen. Ich dachte nicht daran, dass der ADuM !RES treiben wird - und das v.a. nach GND. Kann man zwar halbwegs in Software umgehen, ist aber Mist. '''Die einfachste Fehlerbeseitigung ist, R10 einfach nicht zu bestücken.''' Der ADuM1301 ist trotz des fehlenden Features die günstigste Lösung. Der Reset des Mikrocontrollers (und damit das Wechseln in den Bootloader) kann auch per Kommando ausgelöst werden. Wer will, kann jedoch auch einen Hotfix implementieren: Dazu muss das obere Pad von R10 von der Leiterbahn getrennt werden (rot). Auf den Pads von R18 (rechts) und R10 kann nun ein BSS138 verdreht aufgesetzt werden. Das obere Pad muss dabei noch mit Masse verbunden werden (orange). <gallery> Pirozeda_hat_0.1_adum_hotfix.png Pirozeda_hat_0.1_adum_hotfix.jpg </gallery> Achtung: Auch mit diesem Hotfix gibt es einen Fallstrick: Ist die "Raspberry Pi"-Seite Stromlos, geht der Ausgangspin des ADuM auf high, folglich hängt Reset bei low (aktiv). Kann seine Vorteile haben, zum Flashen des Mikrocontrollers aber eher unpraktisch. =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== '''Aufgebaut und erfolgreich getestet.''' Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEProm ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SJ1 || || SJ || |- | 1 || C6 || 100n || C0603 || X7R-G0603 100N |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 2 || R3, R4 || 3k3 || R0603 || RND 0603 1 3,3K |} Aktuell gibt es noch keine weitere Unterstützung hierfür. Es handelt sich also eher um ein Gimmick. Den EEProm kann man sich recht günstig von eBay-Modulen "abernten" - einfach im nächsten Abschnitt weiterlesen. ==Real-Time-Clock== '''Aufgebaut und erfolgreich getestet.''' Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R11, R12 || 0 || R0603 || RND 0603 1 0 |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 2 || R6, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. Der Levelshifter kann nach ersten Testes getrost weggelassen werden. Wem der DS1307 bei Reichelt zu teuer ist, kann sich bei eBay ein Modul mit dem Chip, passendem Quarz (der zufällig dem verwendeten entspricht) und einem ebenfalls passenden EEProm besorgen. Der Batteriehalter passt im aktuellen Design leider nicht. <gallery> EBay-RTC-Module.jpg|RTC-Modul als Bauteilspender </gallery> ==Option: I²C(-OLED) + Taster== '''Noch nicht aufgebaut und getestet.''' Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |} ==Status-LEDs== '''Aufgebaut und erfolgreich getestet.''' Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 3 || R24, R25, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || LED1 || gn || CHIP-LED0603 || |- | 2 || LED2, LED3 || or || CHIP-LED0603 || |} LED1 (mitte) zeigt Aktivität an, LED2 (unten) ist mehr oder weniger die Power-LED. Mehr oder weniger, da sie beim Start der Firmware aktiviert wird (nicht aber im Bootloader). Dadurch kann man sehr schnell erkennen, ob sich die Hardware in einem Bootloop befindet. LED3 (oben) kann vom Raspberry Pi angesteuert werden. Standardmäßig sind in der <code>config.h</code> folgende Zeiten für LED1 eingestellt: * Start der Anwendung: 250 ms * Korrekt empfangene Nachrichten: 10 ms * Fehlerhaft empfangene Nachrichten: 200 ms Damit kann man auf den einen Blick erkennen, ob Daten vernünftig ankommen und verarbeitet werden können. =Aufbau der Hardware= ==Bestücken der Leiterkarte== Die Hardware kann im Prinzip in beliebiger Reihenfolge aufgebaut werden. Trotzdem ist es ratsam, die großen/hohen Bauteile zuletzt aufzulöten. Die Steckkräfte einer 2x20 Buchsenleiste sind vergleichsweise groß. Diese können reduziert werden, indem nicht verwendete Pins aus der Buchsenleiste entfernt werden. Um diese nicht wieder (fragt nicht) zurückstecken zu müssen, hier eine Auflistung der benötigten Pins: 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 15, 17, 20, 25, 27, 28, 30, 34, 37, 39. Oder einfach als Bild: <gallery> Pirozeda_hat_0.1_buchsenleiste_pins.png|benötigte Pins (blau markiert) </gallery> Der Wannenstecker lässt sich am einfachsten auflöten, wenn man die Pads auf einer Seite (egal welche) der Leiterkarte bisschen stärker verzinnt. Dadurch kann man den Konnektor ein wenig verklemmen und vor dem Verlöten besser ausrichten. ==Zuleitung== Als Zuleitung habe ich für die ersten Muster den Artikel LIYY 614 (Steuerleitung 6x0,14mm², ungeschirmt) von Reichelt verwendet. Beim Bestellen habe ich leider mehr auf den Preis als die Schirmung geachtet. In Hinblick darauf, dass der Schirm der Buchse im Regler eh nicht mit Masse verbunden ist, ist es eine ziemliche Fummelarbeit, diese mit dem Massepin zu verbinden. Erkenntnisse über die maximale Leitungslänge gibt es noch nicht. Der Vorteil dieser Leitung ist: die Adern können direkt im Pfostenverbinder verpresst werden: <gallery> Pirozeda_hat_0.1_pfosten.jpg </gallery> Ich habe mich für folgende Farbgebung entschieden, beim Pinmapping selbst gibt es keine Wahl: {| class="wikitable" ! Mini-DIN || Signal || Farbe || Wannenstecker |- | 3 || MISO || grau || 1 |- | 4 || GND || braun || 3 |- | 5 || 3V3 || rosa || 5 |- | 6 || MOSI || grün || 2 |- | 7 || SCK || gelb || 4 |- | 8 || !CS || weiß || 6 |} Beim Mini-DIN-Stecker sollte darauf geachtet werden, die äußere Hülle nicht komplett über den Rest zu stülpen, da die Buchse beim Regler ziemlich weit nach innen versetzt ist: <gallery> Pirozeda_hat_0.1_minidin.jpg </gallery> =Firmware= Grundsätzlich läuft die Firmware des Originaldesign auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel und viele neue Features fehlen: Ab 0.2: * Status-LEDs * Uptime-Counter * Messung der Versorgungsspannung * Anzeigen von Bootinformationen ** Resetgrund ** Anzahl der vorherigen Reboots ** Dauer der vorherigen Uptime ** Fusecheck ** Watchdog-Info ** Aktivierte Nachrichten * Neustart + Wechsel in den Bootloader per Kommando * Statistik über empfangene Nachrichten (optional) * Timestamps (optional, aktuell nicht kompatibel mit der Backend-Software) * Erneutes übertragen der Headerinformationen * Kann die Firmware bei einem "Katzen-Paket" miauen. Einfach nur weil. ==Konfiguration== Einige der Features müssen vor dem Kompilieren aktiviert bzw. eingestellt werden. Die Schalter und Defines hierfür befinden sich in zwei Header-Dateien: <code>config.h</code> * <code>PIROZEDA_KITTY_DEBUG</code>: Anzeigen der "Katzen-Pakete" (Vorgabe: inaktiv) * <code>PIROZEDA_TIMESTAMPS</code>: Anzeigen der Timestamps (Vorgabe: inaktiv) * <code>PIROZEDA_WDT_TIMEOUT</code>: Timeout des Watchdogs (Vorgabe: 4 s) * <code>PIROZEDA_UPTIME</code>: Führen der Uptime, abrufbar über den Befehl (Vorgabe: aktiv) * <code>PIROZEDA_SUPPLY_AVGCNT</code>: Anzahl der Messwerte für die Mittelwertbildung der Systemspannung (Vorgabe: 10, maximal: 32) * <code>PIROZEDA_HEADERCNT</code>: Anzahl der Kopfzeilen-Datensätze, die nach dem Start oder Befehl <code>header</code> angezeigt werden (Vorgabe: 200, maximal: 255) * <code>PIROZEDA_STATUS_LED_BOOT</code>: Leuchtdauer der Status-LED nach dem Start (Vorgabe: 100 -> 250 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXOK</code>: Leuchtdauer der Status-LED bei empfangenem Paket (Vorgabe: 4 -> 10 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXERR</code>: Leuchtdauer der Status-LED bei einem Fehler (Vorgabe: 80 -> 200 ms, maximal: 255) * <code>BOOTLOADER_PASSWORD</code>: "Passwort" zum Wechsel in den Bootloader (Vorgabe: "FwUp", maximal 4 Zeichen, darf keine Teilstrings von Befehlen enthalten) <code>prozeda_cfg.h</code> * <code>PROZEDA_USE_COLUMN_NAMES</code>: Verwenden der Spaltennamen (irrelevant für Pirozeda) * <code>PROZEDA_SUPPORT_DISPLAY</code>: Aktiviert den Empfang von Displaydaten (Vorgabe: aktiv) * <code>PROZEDA_SUPPORT_HEADER</code>: Aktiviert den Empfang von Kopfzeilen-Datensätzen (Vorgabe: aktiv) * <code>PROZEDA_IGNORE_KITTY</code>: Ignorieren von Katzen-Paketen, andernfalls werden Fehler ausgegeben (Vorgabe: aktiv) * <code>PROZEDA_MSG_MAXTICKS</code>: Ticks, nach denen ein Paket als abgeschlossen erkannt wird, sollte nur bei Anpassung der CPU-Frequenz angepasst werden (Vorgabe: 3) ==Befehle== Neu ist ab v0.2, dass Befehle an den Mikrocontroller gesendet werden können. Je nach Konfiguration sind dies: * <code>reset</code>: Neustart * <code>uptime</code>: Anzeige der Laufzeit * <code>bootinfo</code>: Anzeigen der Infos, die auch beim (Neu-)Start angezeigt werden * <code>header</code>: Header werden gemäß <code>PIROZEDA_HEADERCNT</code> erneut ausgegeben * <code>stats</code>: Anzeigen der Statistik über empfangene Nachrichten und Empfangsfehler Alle Befehle sind Case-sensitive. ==Flashen der Firmware== Mit den Möglichkeiten steigt die Komplexität. Dadurch dass der die Hardware für die Verwendung mit und ohne Bootloader ausgelegt ist, gibt es mehrere "Pfade" für das Flashen. Wer auf Nummer sicher gehen will, lädt einfach Bootloader und Firmware auf den Mikrocontroller herunter. Selbst wenn man "nur" die Variante mit unidirektionalem UART hat - die Brücken Versorgung und für den UART zum Mikrocontroller ist schneller gelötet als die Stiftleiste für den ISP-Port. Das Einlöten einer wahnsinnig hohen Stiftleiste kann übrigens umgangen werden, indem eine Stiftleiste in das Programmierkabel gesteckt und im Footprint der Buchse "verkeilt" wird. Wirklich keine Dauerlösung aber im Idealfall muss man es nur einmal machen. ===Über Raspberry Pi=== Zunächst muss, wenn nicht schon geschehen, über <code>sudo raspi-config</code> das SPI-Interface aktiviert (reboot nicht vergessen) und [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer#Installation_der_Compiler AVRDUDE installiert] werden. Den Regler vom HAT trennen, nicht vergessen, dass R10 oder der Hotfix entfernt werden muss, falls der ADuM-Isolator verwendet und einseitig versorgt (also nicht auf dem Raspi steckt) wird und anschließend den SPI-Port mit SV2 verbinden. {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin |- | MISO || 1 || BCM 9 || 21 |- | 3V3 || 2 || 3V3 || 17 |- | SCK || 3 || BCM 11 || 23 |- | MOSI || 4 || BCM 10 || 19 |- | !RES || 5 || BCM 25 || 22 |- | GND || 6 || GND || 20 |} ====Mit Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = FC }} Die empfohlene Variante (auch wenn man nicht beabsichtigt, den Bootloader zu nutzen). Mit Bootloader sind das folgende Befehle: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0xFC:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_fboot_0.2.hex" </source> ====Ohne Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} 'cause I ain't gonna judge you <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_0.2.hex" </source> ==Update der Firmware== In Sachen Bootloader bin ich ein großer Fan von [https://www.mikrocontroller.net/articles/AVR_Bootloader_FastBoot_von_Peter_Dannegger Peter Danneggers Fastboot]. Er ist klein, schnell und zuverlässig. Um einen kleinen Unterschied zu machen, lautet das Passwort zum Starten nicht "Peda" sondern "FwUp", was ein kleines Problem mit sich bringt. "Peda" ist nicht nur der Spitzname vom Autor, das "a" wird zur automatischen Baudratenerkennung verwendet. Das von mir gewählte Passwort hat das nicht zu bieten. Was mir bei der Verwendung von [https://luani.de/projekte/updateloader/ UpdateLoader] aufgefallen ist: es funktioniert trotzdem. Ganz einfach, weil der Autor ein "a" voranstellt. Das funktioniert dann auch mit so gut wie allen anderen Download-Tools. ===Mit Bootloader=== Das Firmware-Update funktioniert nur bei bidirektionaler UART-Kommunikation mit dem Mikrocontroller, also bei der Variante Direkt und ADuM-Isolator. Wenn man mutig ist, kann man bei der Optokoppler-Variante R19 und R27 bestückt werden. In jedem Fall muss die Mikrocontroller-Seite mit Strom versorgt werden, also am einfachsten am Solarregler angeschlossen lassen. Berhard M. (boregard) hat das Programm [https://www.mikrocontroller.net/topic/73196#1067153 lboot] (auch im Download-Paket) geschrieben, das unter Linux mit dem schönen Fastboot von Peter Danegger spricht. Damit der Download funktioniert, muss das Pirozeda-Backend (und andere Software, die auf das UART-Interface zugreift) beendet werden. <source lang="shell"> ./bootloader -d /dev/serial0 -b 115200 -t 1024 -p pirozeda_0.2.hex -P aFwUp </source> ===Ohne Bootloader=== siehe [[#Flashen_der_Firmware]] =Einrichten der Optionen= ==HAT-ID== Wie bereits weiter oben geschrieben, ist der HAT-EEProm momentan eher ein Gimmick als wirklich genutztes Feature. Die Anwendung zur Generierung der Daten kann im [https://github.com/raspberrypi/hats/tree/master/eepromutils GitHub-Repo] vom Raspberry Pi heruntergeladen werden. Da der EEProm im normalen Betrieb schreibgeschützt ist, muss SJ1 gebrückt werden - am besten mit einem guten Klecks Lötzinn. Anschließend kann mit dem Script eepflash.sh (liegt dem Download-Paket bei) das EEProm-Image geschrieben werden: <source lang="bash"> sudo ./eepflash.sh -w -f=pirozeda-hat_id.eep -t=24c32 -a=50 </source> Aktuell sind weder Product-ID noch Version-ID vergeben, ansonsten ist die Konfiguration wie folgt: <pre> # Start of atom #0 of type 0x0001 and length 60 # Vendor info product_uuid 9edc3aef-683c-4007-b2f2-3ea4969b1737 product_id 0x0000 product_ver 0x0000 vendor "hobbyelektronik.org" # length=19 product "Pirozeda HAT v0.1" # length=17 # End of atom. CRC16=0x9a75 # Start of atom #1 of type 0x0002 and length 32 # GPIO map info gpio_drive 0 gpio_slew 0 gpio_hysteresis 0 back_power 0 # GPIO FUNCTION PULL # ---- -------- ---- setgpio 22 INPUT UP setgpio 26 OUTPUT NONE </pre> ==RTC== Die [http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-RTC/index.html Netzmafia] hat einen recht guten Artikel, wie man die hwclock bedient. Wer sich nicht einlesen will, hier im Schnelldurchlauf: Testen der RTC: <source lang="shell"> #call bash as superuser, this is needed to get the echo working properly sudo bash modprobe rtc-ds1307 echo "ds1307 0x68" > /sys/class/i2c-adapter/i2c-1/new_device #Auslesen der Uhr hwclock --debug -r exit </source> Dauerhaftes aktivieren der RTC: <source lang="shell"> sudo bash # enable module echo "# enable DS1307-RTC" >> /etc/modules echo "rtc-ds1307" >> /etc/modules # remove fake-hwclock update-rc.d -f fake-hwclock disable update-rc.d -f fake-hwclock remove apt-get remove fake-hwclock # overwrite prepared configuration of hwclock cp /etc/init.d/hwclock.sh ./hwclock.old cat ./hwclock.new > /etc/init.d/hwclock.sh # enable start/stop script update-rc.d hwclock.sh enable exit </source> Laut Anleitung von Netzmafia muss die Datei <code>/etc/init.d/hwclock.sh</code> noch wie folgt angepasst werden: <source lang="text"> Nun muss noch das Start/Stopp-Script für die RTC angepasst werden. Dazu wird (als root-User) die Datei /etc/init.d/hwclock.sh mit dem Editor bearbeitet. Zunächst tragen Sie am Anfang des Scripts die Default-Wert ein bzw. überprüfen diese: # These defaults are user-overridable in /etc/default/hwclock BADYEAR=no HWCLOCKACCESS=yes HWCLOCKPARS=' --noadjfile --utc' HCTOSYS_DEVICE=rtc0 Nach der Zeile 'case "$1" in start)' werden die folgenden drei Zeilen auskommentieren ('#' davorsetzen): #if [ -d /run/udev ] || [ -d /dev/.udev ]; then # return 0 #fi </source> Um das zu vereinfachen, habe ich eine SH-Datei vorbereitet, natürlich muss sich diese (<code>hwclock.new</code>) im gleichen Verzeichnis liegen, damit es funktioniert. Im Ordner <code>options/rtc</code> befindet sich sowohl die <code>rtc-test.sh</code> als auch <code>rtc-enable.sh</code>. Da diese über meinen Windows-PC gewandert sind und dadurch ihre Dateieigenschaften verloren haben, müssen sie entweder als ausführbar markiert werden oder mit <code>/bin/bash</code> gestartet werden: <source lang="shell"> sudo /bin/bash rtc-test.sh </source> ==I²C + Taster== Für die Verwendung des I²C muss eigentlich nur in <code>raspi-config</code> das I²C-Interface aktiviert werden. Mit der Konfiguration im ID-EEPRom wird der Taster in den Device-Tree eingebunden, allerdings kann er prinzipiell auch ohne angesprochen werden. =Backend= Das Back- und Frontend aus [[Pirozeda]] kann prinzipiell weiterverwendet werden. Es gibt allerdings noch keinen Support der neuen Features. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Verbesserungsmöglichkeiten= * Korrektur der Reset-Beschaltung * ESD-Schutz hinzufügen. Aktuell können auf den Footprints von C7, C11 und C14 ESD-Schutzdioden wie B72500D50A60 von Reichelt bestückt werden. Allerdings ist die Positionierung nicht ideal * Stiftwanne für den SPI-Schnittstelle oben auf der Leiterkarte platzieren * Die Widerstände für die Direktverbindung so platzieren, dass sie für das Bootloader-Update einfacher bestückt werden können (oder gleich Jumper) * Hinzufügen der Batteriehalter der billigen RTC-Module (Recycling FTW!) * Entfernen des nicht benötigten I²C-Levelshifters * Vermeiden von Backfeed in der Direkt-Variante =Download= [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format * Quellen des Bootloaders von Peter Dannegger * Quellen der Firmware + flashbare Images * Scripts für die Einrichtung der Optionen [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 2bd722b1d200246bd4512c2146b31d30de5cebf1 1328 1327 2019-03-21T21:14:41Z Chris 2 /* RTC */ Umbrüche korrigiert wikitext text/x-wiki Wie bereits im [[Pirozeda|Hauptartikel]] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar Geschmackssache aber in Hinblick auf Platz das Beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== '''Noch nicht aufgebaut und getestet.''' Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist, dass neben der gemeinsamen Masse mit der Solaranlage Backfeed entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Diese Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== '''Aufgebaut und erfolgreich getestet.''' Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_opto_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_opto_assy.png|Bestückungsplan mit Optokoppler pirozeda_hat_0.1_opto.jpg|Aufgebauter HAT - es passt sogar ein MJ-Quarz </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R13, R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== '''Aufgebaut und weitestgehend erfolgreich getestet.''' Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator pirozeda_hat_0.1_adum.jpg|Aufgebauter HAT mit Hotfix </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 1 || R9 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} Bei der Schaltungsentwicklung hat sich leider ein dummer Fehler eingeschlichen. Ich dachte nicht daran, dass der ADuM !RES treiben wird - und das v.a. nach GND. Kann man zwar halbwegs in Software umgehen, ist aber Mist. '''Die einfachste Fehlerbeseitigung ist, R10 einfach nicht zu bestücken.''' Der ADuM1301 ist trotz des fehlenden Features die günstigste Lösung. Der Reset des Mikrocontrollers (und damit das Wechseln in den Bootloader) kann auch per Kommando ausgelöst werden. Wer will, kann jedoch auch einen Hotfix implementieren: Dazu muss das obere Pad von R10 von der Leiterbahn getrennt werden (rot). Auf den Pads von R18 (rechts) und R10 kann nun ein BSS138 verdreht aufgesetzt werden. Das obere Pad muss dabei noch mit Masse verbunden werden (orange). <gallery> Pirozeda_hat_0.1_adum_hotfix.png Pirozeda_hat_0.1_adum_hotfix.jpg </gallery> Achtung: Auch mit diesem Hotfix gibt es einen Fallstrick: Ist die "Raspberry Pi"-Seite Stromlos, geht der Ausgangspin des ADuM auf high, folglich hängt Reset bei low (aktiv). Kann seine Vorteile haben, zum Flashen des Mikrocontrollers aber eher unpraktisch. =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== '''Aufgebaut und erfolgreich getestet.''' Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEProm ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SJ1 || || SJ || |- | 1 || C6 || 100n || C0603 || X7R-G0603 100N |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 2 || R3, R4 || 3k3 || R0603 || RND 0603 1 3,3K |} Aktuell gibt es noch keine weitere Unterstützung hierfür. Es handelt sich also eher um ein Gimmick. Den EEProm kann man sich recht günstig von eBay-Modulen "abernten" - einfach im nächsten Abschnitt weiterlesen. ==Real-Time-Clock== '''Aufgebaut und erfolgreich getestet.''' Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R11, R12 || 0 || R0603 || RND 0603 1 0 |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 2 || R6, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. Der Levelshifter kann nach ersten Testes getrost weggelassen werden. Wem der DS1307 bei Reichelt zu teuer ist, kann sich bei eBay ein Modul mit dem Chip, passendem Quarz (der zufällig dem verwendeten entspricht) und einem ebenfalls passenden EEProm besorgen. Der Batteriehalter passt im aktuellen Design leider nicht. <gallery> EBay-RTC-Module.jpg|RTC-Modul als Bauteilspender </gallery> ==Option: I²C(-OLED) + Taster== '''Noch nicht aufgebaut und getestet.''' Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |} ==Status-LEDs== '''Aufgebaut und erfolgreich getestet.''' Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 3 || R24, R25, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || LED1 || gn || CHIP-LED0603 || |- | 2 || LED2, LED3 || or || CHIP-LED0603 || |} LED1 (mitte) zeigt Aktivität an, LED2 (unten) ist mehr oder weniger die Power-LED. Mehr oder weniger, da sie beim Start der Firmware aktiviert wird (nicht aber im Bootloader). Dadurch kann man sehr schnell erkennen, ob sich die Hardware in einem Bootloop befindet. LED3 (oben) kann vom Raspberry Pi angesteuert werden. Standardmäßig sind in der <code>config.h</code> folgende Zeiten für LED1 eingestellt: * Start der Anwendung: 250 ms * Korrekt empfangene Nachrichten: 10 ms * Fehlerhaft empfangene Nachrichten: 200 ms Damit kann man auf den einen Blick erkennen, ob Daten vernünftig ankommen und verarbeitet werden können. =Aufbau der Hardware= ==Bestücken der Leiterkarte== Die Hardware kann im Prinzip in beliebiger Reihenfolge aufgebaut werden. Trotzdem ist es ratsam, die großen/hohen Bauteile zuletzt aufzulöten. Die Steckkräfte einer 2x20 Buchsenleiste sind vergleichsweise groß. Diese können reduziert werden, indem nicht verwendete Pins aus der Buchsenleiste entfernt werden. Um diese nicht wieder (fragt nicht) zurückstecken zu müssen, hier eine Auflistung der benötigten Pins: 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 15, 17, 20, 25, 27, 28, 30, 34, 37, 39. Oder einfach als Bild: <gallery> Pirozeda_hat_0.1_buchsenleiste_pins.png|benötigte Pins (blau markiert) </gallery> Der Wannenstecker lässt sich am einfachsten auflöten, wenn man die Pads auf einer Seite (egal welche) der Leiterkarte bisschen stärker verzinnt. Dadurch kann man den Konnektor ein wenig verklemmen und vor dem Verlöten besser ausrichten. ==Zuleitung== Als Zuleitung habe ich für die ersten Muster den Artikel LIYY 614 (Steuerleitung 6x0,14mm², ungeschirmt) von Reichelt verwendet. Beim Bestellen habe ich leider mehr auf den Preis als die Schirmung geachtet. In Hinblick darauf, dass der Schirm der Buchse im Regler eh nicht mit Masse verbunden ist, ist es eine ziemliche Fummelarbeit, diese mit dem Massepin zu verbinden. Erkenntnisse über die maximale Leitungslänge gibt es noch nicht. Der Vorteil dieser Leitung ist: die Adern können direkt im Pfostenverbinder verpresst werden: <gallery> Pirozeda_hat_0.1_pfosten.jpg </gallery> Ich habe mich für folgende Farbgebung entschieden, beim Pinmapping selbst gibt es keine Wahl: {| class="wikitable" ! Mini-DIN || Signal || Farbe || Wannenstecker |- | 3 || MISO || grau || 1 |- | 4 || GND || braun || 3 |- | 5 || 3V3 || rosa || 5 |- | 6 || MOSI || grün || 2 |- | 7 || SCK || gelb || 4 |- | 8 || !CS || weiß || 6 |} Beim Mini-DIN-Stecker sollte darauf geachtet werden, die äußere Hülle nicht komplett über den Rest zu stülpen, da die Buchse beim Regler ziemlich weit nach innen versetzt ist: <gallery> Pirozeda_hat_0.1_minidin.jpg </gallery> =Firmware= Grundsätzlich läuft die Firmware des Originaldesign auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel und viele neue Features fehlen: Ab 0.2: * Status-LEDs * Uptime-Counter * Messung der Versorgungsspannung * Anzeigen von Bootinformationen ** Resetgrund ** Anzahl der vorherigen Reboots ** Dauer der vorherigen Uptime ** Fusecheck ** Watchdog-Info ** Aktivierte Nachrichten * Neustart + Wechsel in den Bootloader per Kommando * Statistik über empfangene Nachrichten (optional) * Timestamps (optional, aktuell nicht kompatibel mit der Backend-Software) * Erneutes übertragen der Headerinformationen * Kann die Firmware bei einem "Katzen-Paket" miauen. Einfach nur weil. ==Konfiguration== Einige der Features müssen vor dem Kompilieren aktiviert bzw. eingestellt werden. Die Schalter und Defines hierfür befinden sich in zwei Header-Dateien: <code>config.h</code> * <code>PIROZEDA_KITTY_DEBUG</code>: Anzeigen der "Katzen-Pakete" (Vorgabe: inaktiv) * <code>PIROZEDA_TIMESTAMPS</code>: Anzeigen der Timestamps (Vorgabe: inaktiv) * <code>PIROZEDA_WDT_TIMEOUT</code>: Timeout des Watchdogs (Vorgabe: 4 s) * <code>PIROZEDA_UPTIME</code>: Führen der Uptime, abrufbar über den Befehl (Vorgabe: aktiv) * <code>PIROZEDA_SUPPLY_AVGCNT</code>: Anzahl der Messwerte für die Mittelwertbildung der Systemspannung (Vorgabe: 10, maximal: 32) * <code>PIROZEDA_HEADERCNT</code>: Anzahl der Kopfzeilen-Datensätze, die nach dem Start oder Befehl <code>header</code> angezeigt werden (Vorgabe: 200, maximal: 255) * <code>PIROZEDA_STATUS_LED_BOOT</code>: Leuchtdauer der Status-LED nach dem Start (Vorgabe: 100 -> 250 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXOK</code>: Leuchtdauer der Status-LED bei empfangenem Paket (Vorgabe: 4 -> 10 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXERR</code>: Leuchtdauer der Status-LED bei einem Fehler (Vorgabe: 80 -> 200 ms, maximal: 255) * <code>BOOTLOADER_PASSWORD</code>: "Passwort" zum Wechsel in den Bootloader (Vorgabe: "FwUp", maximal 4 Zeichen, darf keine Teilstrings von Befehlen enthalten) <code>prozeda_cfg.h</code> * <code>PROZEDA_USE_COLUMN_NAMES</code>: Verwenden der Spaltennamen (irrelevant für Pirozeda) * <code>PROZEDA_SUPPORT_DISPLAY</code>: Aktiviert den Empfang von Displaydaten (Vorgabe: aktiv) * <code>PROZEDA_SUPPORT_HEADER</code>: Aktiviert den Empfang von Kopfzeilen-Datensätzen (Vorgabe: aktiv) * <code>PROZEDA_IGNORE_KITTY</code>: Ignorieren von Katzen-Paketen, andernfalls werden Fehler ausgegeben (Vorgabe: aktiv) * <code>PROZEDA_MSG_MAXTICKS</code>: Ticks, nach denen ein Paket als abgeschlossen erkannt wird, sollte nur bei Anpassung der CPU-Frequenz angepasst werden (Vorgabe: 3) ==Befehle== Neu ist ab v0.2, dass Befehle an den Mikrocontroller gesendet werden können. Je nach Konfiguration sind dies: * <code>reset</code>: Neustart * <code>uptime</code>: Anzeige der Laufzeit * <code>bootinfo</code>: Anzeigen der Infos, die auch beim (Neu-)Start angezeigt werden * <code>header</code>: Header werden gemäß <code>PIROZEDA_HEADERCNT</code> erneut ausgegeben * <code>stats</code>: Anzeigen der Statistik über empfangene Nachrichten und Empfangsfehler Alle Befehle sind Case-sensitive. ==Flashen der Firmware== Mit den Möglichkeiten steigt die Komplexität. Dadurch dass der die Hardware für die Verwendung mit und ohne Bootloader ausgelegt ist, gibt es mehrere "Pfade" für das Flashen. Wer auf Nummer sicher gehen will, lädt einfach Bootloader und Firmware auf den Mikrocontroller herunter. Selbst wenn man "nur" die Variante mit unidirektionalem UART hat - die Brücken Versorgung und für den UART zum Mikrocontroller ist schneller gelötet als die Stiftleiste für den ISP-Port. Das Einlöten einer wahnsinnig hohen Stiftleiste kann übrigens umgangen werden, indem eine Stiftleiste in das Programmierkabel gesteckt und im Footprint der Buchse "verkeilt" wird. Wirklich keine Dauerlösung aber im Idealfall muss man es nur einmal machen. ===Über Raspberry Pi=== Zunächst muss, wenn nicht schon geschehen, über <code>sudo raspi-config</code> das SPI-Interface aktiviert (reboot nicht vergessen) und [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer#Installation_der_Compiler AVRDUDE installiert] werden. Den Regler vom HAT trennen, nicht vergessen, dass R10 oder der Hotfix entfernt werden muss, falls der ADuM-Isolator verwendet und einseitig versorgt (also nicht auf dem Raspi steckt) wird und anschließend den SPI-Port mit SV2 verbinden. {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin |- | MISO || 1 || BCM 9 || 21 |- | 3V3 || 2 || 3V3 || 17 |- | SCK || 3 || BCM 11 || 23 |- | MOSI || 4 || BCM 10 || 19 |- | !RES || 5 || BCM 25 || 22 |- | GND || 6 || GND || 20 |} ====Mit Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = FC }} Die empfohlene Variante (auch wenn man nicht beabsichtigt, den Bootloader zu nutzen). Mit Bootloader sind das folgende Befehle: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0xFC:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_fboot_0.2.hex" </source> ====Ohne Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} 'cause I ain't gonna judge you <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_0.2.hex" </source> ==Update der Firmware== In Sachen Bootloader bin ich ein großer Fan von [https://www.mikrocontroller.net/articles/AVR_Bootloader_FastBoot_von_Peter_Dannegger Peter Danneggers Fastboot]. Er ist klein, schnell und zuverlässig. Um einen kleinen Unterschied zu machen, lautet das Passwort zum Starten nicht "Peda" sondern "FwUp", was ein kleines Problem mit sich bringt. "Peda" ist nicht nur der Spitzname vom Autor, das "a" wird zur automatischen Baudratenerkennung verwendet. Das von mir gewählte Passwort hat das nicht zu bieten. Was mir bei der Verwendung von [https://luani.de/projekte/updateloader/ UpdateLoader] aufgefallen ist: es funktioniert trotzdem. Ganz einfach, weil der Autor ein "a" voranstellt. Das funktioniert dann auch mit so gut wie allen anderen Download-Tools. ===Mit Bootloader=== Das Firmware-Update funktioniert nur bei bidirektionaler UART-Kommunikation mit dem Mikrocontroller, also bei der Variante Direkt und ADuM-Isolator. Wenn man mutig ist, kann man bei der Optokoppler-Variante R19 und R27 bestückt werden. In jedem Fall muss die Mikrocontroller-Seite mit Strom versorgt werden, also am einfachsten am Solarregler angeschlossen lassen. Berhard M. (boregard) hat das Programm [https://www.mikrocontroller.net/topic/73196#1067153 lboot] (auch im Download-Paket) geschrieben, das unter Linux mit dem schönen Fastboot von Peter Danegger spricht. Damit der Download funktioniert, muss das Pirozeda-Backend (und andere Software, die auf das UART-Interface zugreift) beendet werden. <source lang="shell"> ./bootloader -d /dev/serial0 -b 115200 -t 1024 -p pirozeda_0.2.hex -P aFwUp </source> ===Ohne Bootloader=== siehe [[#Flashen_der_Firmware]] =Einrichten der Optionen= ==HAT-ID== Wie bereits weiter oben geschrieben, ist der HAT-EEProm momentan eher ein Gimmick als wirklich genutztes Feature. Die Anwendung zur Generierung der Daten kann im [https://github.com/raspberrypi/hats/tree/master/eepromutils GitHub-Repo] vom Raspberry Pi heruntergeladen werden. Da der EEProm im normalen Betrieb schreibgeschützt ist, muss SJ1 gebrückt werden - am besten mit einem guten Klecks Lötzinn. Anschließend kann mit dem Script eepflash.sh (liegt dem Download-Paket bei) das EEProm-Image geschrieben werden: <source lang="bash"> sudo ./eepflash.sh -w -f=pirozeda-hat_id.eep -t=24c32 -a=50 </source> Aktuell sind weder Product-ID noch Version-ID vergeben, ansonsten ist die Konfiguration wie folgt: <pre> # Start of atom #0 of type 0x0001 and length 60 # Vendor info product_uuid 9edc3aef-683c-4007-b2f2-3ea4969b1737 product_id 0x0000 product_ver 0x0000 vendor "hobbyelektronik.org" # length=19 product "Pirozeda HAT v0.1" # length=17 # End of atom. CRC16=0x9a75 # Start of atom #1 of type 0x0002 and length 32 # GPIO map info gpio_drive 0 gpio_slew 0 gpio_hysteresis 0 back_power 0 # GPIO FUNCTION PULL # ---- -------- ---- setgpio 22 INPUT UP setgpio 26 OUTPUT NONE </pre> ==RTC== Die [http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-RTC/index.html Netzmafia] hat einen recht guten Artikel, wie man die hwclock bedient. Wer sich nicht einlesen will, hier im Schnelldurchlauf: Testen der RTC: <source lang="shell"> #call bash as superuser, this is needed to get the echo working properly sudo bash modprobe rtc-ds1307 echo "ds1307 0x68" > /sys/class/i2c-adapter/i2c-1/new_device #Auslesen der Uhr hwclock --debug -r exit </source> Dauerhaftes aktivieren der RTC: <source lang="shell"> sudo bash # enable module echo "# enable DS1307-RTC" >> /etc/modules echo "rtc-ds1307" >> /etc/modules # remove fake-hwclock update-rc.d -f fake-hwclock disable update-rc.d -f fake-hwclock remove apt-get remove fake-hwclock # overwrite prepared configuration of hwclock cp /etc/init.d/hwclock.sh ./hwclock.old cat ./hwclock.new > /etc/init.d/hwclock.sh # enable start/stop script update-rc.d hwclock.sh enable exit </source> Laut Anleitung von Netzmafia muss die Datei <code>/etc/init.d/hwclock.sh</code> noch wie folgt angepasst werden: <source lang="text"> Nun muss noch das Start/Stopp-Script für die RTC angepasst werden. Dazu wird (als root-User) die Datei /etc/init.d/hwclock.sh mit dem Editor bearbeitet. Zunächst tragen Sie am Anfang des Scripts die Default-Wert ein bzw. überprüfen diese: # These defaults are user-overridable in /etc/default/hwclock BADYEAR=no HWCLOCKACCESS=yes HWCLOCKPARS=' --noadjfile --utc' HCTOSYS_DEVICE=rtc0 Nach der Zeile 'case "$1" in start)' werden die folgenden drei Zeilen auskommentieren ('#' davorsetzen): #if [ -d /run/udev ] || [ -d /dev/.udev ]; then # return 0 #fi </source> Um das zu vereinfachen, habe ich eine SH-Datei vorbereitet, natürlich muss sich diese (<code>hwclock.new</code>) im gleichen Verzeichnis liegen, damit es funktioniert. Im Ordner <code>options/rtc</code> befindet sich sowohl die <code>rtc-test.sh</code> als auch <code>rtc-enable.sh</code>. Da diese über meinen Windows-PC gewandert sind und dadurch ihre Dateieigenschaften verloren haben, müssen sie entweder als ausführbar markiert werden oder mit <code>/bin/bash</code> gestartet werden: <source lang="shell"> sudo /bin/bash rtc-test.sh </source> ==I²C + Taster== Für die Verwendung des I²C muss eigentlich nur in <code>raspi-config</code> das I²C-Interface aktiviert werden. Mit der Konfiguration im ID-EEPRom wird der Taster in den Device-Tree eingebunden, allerdings kann er prinzipiell auch ohne angesprochen werden. =Backend= Das Back- und Frontend aus [[Pirozeda]] kann prinzipiell weiterverwendet werden. Es gibt allerdings noch keinen Support der neuen Features. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Verbesserungsmöglichkeiten= * Korrektur der Reset-Beschaltung * ESD-Schutz hinzufügen. Aktuell können auf den Footprints von C7, C11 und C14 ESD-Schutzdioden wie B72500D50A60 von Reichelt bestückt werden. Allerdings ist die Positionierung nicht ideal * Stiftwanne für den SPI-Schnittstelle oben auf der Leiterkarte platzieren * Die Widerstände für die Direktverbindung so platzieren, dass sie für das Bootloader-Update einfacher bestückt werden können (oder gleich Jumper) * Hinzufügen der Batteriehalter der billigen RTC-Module (Recycling FTW!) * Entfernen des nicht benötigten I²C-Levelshifters * Vermeiden von Backfeed in der Direkt-Variante =Download= [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format * Quellen des Bootloaders von Peter Dannegger * Quellen der Firmware + flashbare Images * Scripts für die Einrichtung der Optionen [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] b0c919ce792697bb99abf8ec02479199d6107413 1330 1328 2019-03-21T21:33:32Z Chris 2 Artikelbild wikitext text/x-wiki [[Datei:Pirozeda_hat_rpizerow.jpg|200px|thumb|Pirozeda-HAT mit ADuM-Isolator auf Raspberry Pi Zero W]] Wie bereits im [[Pirozeda|Hauptartikel]] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar Geschmackssache aber in Hinblick auf Platz das Beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== '''Noch nicht aufgebaut und getestet.''' Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist, dass neben der gemeinsamen Masse mit der Solaranlage Backfeed entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Diese Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== '''Aufgebaut und erfolgreich getestet.''' Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_opto_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_opto_assy.png|Bestückungsplan mit Optokoppler pirozeda_hat_0.1_opto.jpg|Aufgebauter HAT - es passt sogar ein MJ-Quarz </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R13, R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== '''Aufgebaut und weitestgehend erfolgreich getestet.''' Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator pirozeda_hat_0.1_adum.jpg|Aufgebauter HAT mit Hotfix </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 1 || R9 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} Bei der Schaltungsentwicklung hat sich leider ein dummer Fehler eingeschlichen. Ich dachte nicht daran, dass der ADuM !RES treiben wird - und das v.a. nach GND. Kann man zwar halbwegs in Software umgehen, ist aber Mist. '''Die einfachste Fehlerbeseitigung ist, R10 einfach nicht zu bestücken.''' Der ADuM1301 ist trotz des fehlenden Features die günstigste Lösung. Der Reset des Mikrocontrollers (und damit das Wechseln in den Bootloader) kann auch per Kommando ausgelöst werden. Wer will, kann jedoch auch einen Hotfix implementieren: Dazu muss das obere Pad von R10 von der Leiterbahn getrennt werden (rot). Auf den Pads von R18 (rechts) und R10 kann nun ein BSS138 verdreht aufgesetzt werden. Das obere Pad muss dabei noch mit Masse verbunden werden (orange). <gallery> Pirozeda_hat_0.1_adum_hotfix.png Pirozeda_hat_0.1_adum_hotfix.jpg </gallery> Achtung: Auch mit diesem Hotfix gibt es einen Fallstrick: Ist die "Raspberry Pi"-Seite Stromlos, geht der Ausgangspin des ADuM auf high, folglich hängt Reset bei low (aktiv). Kann seine Vorteile haben, zum Flashen des Mikrocontrollers aber eher unpraktisch. =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== '''Aufgebaut und erfolgreich getestet.''' Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEProm ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SJ1 || || SJ || |- | 1 || C6 || 100n || C0603 || X7R-G0603 100N |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 2 || R3, R4 || 3k3 || R0603 || RND 0603 1 3,3K |} Aktuell gibt es noch keine weitere Unterstützung hierfür. Es handelt sich also eher um ein Gimmick. Den EEProm kann man sich recht günstig von eBay-Modulen "abernten" - einfach im nächsten Abschnitt weiterlesen. ==Real-Time-Clock== '''Aufgebaut und erfolgreich getestet.''' Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R11, R12 || 0 || R0603 || RND 0603 1 0 |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 2 || R6, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. Der Levelshifter kann nach ersten Testes getrost weggelassen werden. Wem der DS1307 bei Reichelt zu teuer ist, kann sich bei eBay ein Modul mit dem Chip, passendem Quarz (der zufällig dem verwendeten entspricht) und einem ebenfalls passenden EEProm besorgen. Der Batteriehalter passt im aktuellen Design leider nicht. <gallery> EBay-RTC-Module.jpg|RTC-Modul als Bauteilspender </gallery> ==Option: I²C(-OLED) + Taster== '''Noch nicht aufgebaut und getestet.''' Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |} ==Status-LEDs== '''Aufgebaut und erfolgreich getestet.''' Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 3 || R24, R25, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || LED1 || gn || CHIP-LED0603 || |- | 2 || LED2, LED3 || or || CHIP-LED0603 || |} LED1 (mitte) zeigt Aktivität an, LED2 (unten) ist mehr oder weniger die Power-LED. Mehr oder weniger, da sie beim Start der Firmware aktiviert wird (nicht aber im Bootloader). Dadurch kann man sehr schnell erkennen, ob sich die Hardware in einem Bootloop befindet. LED3 (oben) kann vom Raspberry Pi angesteuert werden. Standardmäßig sind in der <code>config.h</code> folgende Zeiten für LED1 eingestellt: * Start der Anwendung: 250 ms * Korrekt empfangene Nachrichten: 10 ms * Fehlerhaft empfangene Nachrichten: 200 ms Damit kann man auf den einen Blick erkennen, ob Daten vernünftig ankommen und verarbeitet werden können. =Aufbau der Hardware= ==Bestücken der Leiterkarte== Die Hardware kann im Prinzip in beliebiger Reihenfolge aufgebaut werden. Trotzdem ist es ratsam, die großen/hohen Bauteile zuletzt aufzulöten. Die Steckkräfte einer 2x20 Buchsenleiste sind vergleichsweise groß. Diese können reduziert werden, indem nicht verwendete Pins aus der Buchsenleiste entfernt werden. Um diese nicht wieder (fragt nicht) zurückstecken zu müssen, hier eine Auflistung der benötigten Pins: 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 15, 17, 20, 25, 27, 28, 30, 34, 37, 39. Oder einfach als Bild: <gallery> Pirozeda_hat_0.1_buchsenleiste_pins.png|benötigte Pins (blau markiert) </gallery> Der Wannenstecker lässt sich am einfachsten auflöten, wenn man die Pads auf einer Seite (egal welche) der Leiterkarte bisschen stärker verzinnt. Dadurch kann man den Konnektor ein wenig verklemmen und vor dem Verlöten besser ausrichten. ==Zuleitung== Als Zuleitung habe ich für die ersten Muster den Artikel LIYY 614 (Steuerleitung 6x0,14mm², ungeschirmt) von Reichelt verwendet. Beim Bestellen habe ich leider mehr auf den Preis als die Schirmung geachtet. In Hinblick darauf, dass der Schirm der Buchse im Regler eh nicht mit Masse verbunden ist, ist es eine ziemliche Fummelarbeit, diese mit dem Massepin zu verbinden. Erkenntnisse über die maximale Leitungslänge gibt es noch nicht. Der Vorteil dieser Leitung ist: die Adern können direkt im Pfostenverbinder verpresst werden: <gallery> Pirozeda_hat_0.1_pfosten.jpg </gallery> Ich habe mich für folgende Farbgebung entschieden, beim Pinmapping selbst gibt es keine Wahl: {| class="wikitable" ! Mini-DIN || Signal || Farbe || Wannenstecker |- | 3 || MISO || grau || 1 |- | 4 || GND || braun || 3 |- | 5 || 3V3 || rosa || 5 |- | 6 || MOSI || grün || 2 |- | 7 || SCK || gelb || 4 |- | 8 || !CS || weiß || 6 |} Beim Mini-DIN-Stecker sollte darauf geachtet werden, die äußere Hülle nicht komplett über den Rest zu stülpen, da die Buchse beim Regler ziemlich weit nach innen versetzt ist: <gallery> Pirozeda_hat_0.1_minidin.jpg </gallery> =Firmware= Grundsätzlich läuft die Firmware des Originaldesign auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel und viele neue Features fehlen: Ab 0.2: * Status-LEDs * Uptime-Counter * Messung der Versorgungsspannung * Anzeigen von Bootinformationen ** Resetgrund ** Anzahl der vorherigen Reboots ** Dauer der vorherigen Uptime ** Fusecheck ** Watchdog-Info ** Aktivierte Nachrichten * Neustart + Wechsel in den Bootloader per Kommando * Statistik über empfangene Nachrichten (optional) * Timestamps (optional, aktuell nicht kompatibel mit der Backend-Software) * Erneutes übertragen der Headerinformationen * Kann die Firmware bei einem "Katzen-Paket" miauen. Einfach nur weil. ==Konfiguration== Einige der Features müssen vor dem Kompilieren aktiviert bzw. eingestellt werden. Die Schalter und Defines hierfür befinden sich in zwei Header-Dateien: <code>config.h</code> * <code>PIROZEDA_KITTY_DEBUG</code>: Anzeigen der "Katzen-Pakete" (Vorgabe: inaktiv) * <code>PIROZEDA_TIMESTAMPS</code>: Anzeigen der Timestamps (Vorgabe: inaktiv) * <code>PIROZEDA_WDT_TIMEOUT</code>: Timeout des Watchdogs (Vorgabe: 4 s) * <code>PIROZEDA_UPTIME</code>: Führen der Uptime, abrufbar über den Befehl (Vorgabe: aktiv) * <code>PIROZEDA_SUPPLY_AVGCNT</code>: Anzahl der Messwerte für die Mittelwertbildung der Systemspannung (Vorgabe: 10, maximal: 32) * <code>PIROZEDA_HEADERCNT</code>: Anzahl der Kopfzeilen-Datensätze, die nach dem Start oder Befehl <code>header</code> angezeigt werden (Vorgabe: 200, maximal: 255) * <code>PIROZEDA_STATUS_LED_BOOT</code>: Leuchtdauer der Status-LED nach dem Start (Vorgabe: 100 -> 250 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXOK</code>: Leuchtdauer der Status-LED bei empfangenem Paket (Vorgabe: 4 -> 10 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXERR</code>: Leuchtdauer der Status-LED bei einem Fehler (Vorgabe: 80 -> 200 ms, maximal: 255) * <code>BOOTLOADER_PASSWORD</code>: "Passwort" zum Wechsel in den Bootloader (Vorgabe: "FwUp", maximal 4 Zeichen, darf keine Teilstrings von Befehlen enthalten) <code>prozeda_cfg.h</code> * <code>PROZEDA_USE_COLUMN_NAMES</code>: Verwenden der Spaltennamen (irrelevant für Pirozeda) * <code>PROZEDA_SUPPORT_DISPLAY</code>: Aktiviert den Empfang von Displaydaten (Vorgabe: aktiv) * <code>PROZEDA_SUPPORT_HEADER</code>: Aktiviert den Empfang von Kopfzeilen-Datensätzen (Vorgabe: aktiv) * <code>PROZEDA_IGNORE_KITTY</code>: Ignorieren von Katzen-Paketen, andernfalls werden Fehler ausgegeben (Vorgabe: aktiv) * <code>PROZEDA_MSG_MAXTICKS</code>: Ticks, nach denen ein Paket als abgeschlossen erkannt wird, sollte nur bei Anpassung der CPU-Frequenz angepasst werden (Vorgabe: 3) ==Befehle== Neu ist ab v0.2, dass Befehle an den Mikrocontroller gesendet werden können. Je nach Konfiguration sind dies: * <code>reset</code>: Neustart * <code>uptime</code>: Anzeige der Laufzeit * <code>bootinfo</code>: Anzeigen der Infos, die auch beim (Neu-)Start angezeigt werden * <code>header</code>: Header werden gemäß <code>PIROZEDA_HEADERCNT</code> erneut ausgegeben * <code>stats</code>: Anzeigen der Statistik über empfangene Nachrichten und Empfangsfehler Alle Befehle sind Case-sensitive. ==Flashen der Firmware== Mit den Möglichkeiten steigt die Komplexität. Dadurch dass der die Hardware für die Verwendung mit und ohne Bootloader ausgelegt ist, gibt es mehrere "Pfade" für das Flashen. Wer auf Nummer sicher gehen will, lädt einfach Bootloader und Firmware auf den Mikrocontroller herunter. Selbst wenn man "nur" die Variante mit unidirektionalem UART hat - die Brücken Versorgung und für den UART zum Mikrocontroller ist schneller gelötet als die Stiftleiste für den ISP-Port. Das Einlöten einer wahnsinnig hohen Stiftleiste kann übrigens umgangen werden, indem eine Stiftleiste in das Programmierkabel gesteckt und im Footprint der Buchse "verkeilt" wird. Wirklich keine Dauerlösung aber im Idealfall muss man es nur einmal machen. ===Über Raspberry Pi=== Zunächst muss, wenn nicht schon geschehen, über <code>sudo raspi-config</code> das SPI-Interface aktiviert (reboot nicht vergessen) und [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer#Installation_der_Compiler AVRDUDE installiert] werden. Den Regler vom HAT trennen, nicht vergessen, dass R10 oder der Hotfix entfernt werden muss, falls der ADuM-Isolator verwendet und einseitig versorgt (also nicht auf dem Raspi steckt) wird und anschließend den SPI-Port mit SV2 verbinden. {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin |- | MISO || 1 || BCM 9 || 21 |- | 3V3 || 2 || 3V3 || 17 |- | SCK || 3 || BCM 11 || 23 |- | MOSI || 4 || BCM 10 || 19 |- | !RES || 5 || BCM 25 || 22 |- | GND || 6 || GND || 20 |} ====Mit Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = FC }} Die empfohlene Variante (auch wenn man nicht beabsichtigt, den Bootloader zu nutzen). Mit Bootloader sind das folgende Befehle: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0xFC:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_fboot_0.2.hex" </source> ====Ohne Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} 'cause I ain't gonna judge you <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_0.2.hex" </source> ==Update der Firmware== In Sachen Bootloader bin ich ein großer Fan von [https://www.mikrocontroller.net/articles/AVR_Bootloader_FastBoot_von_Peter_Dannegger Peter Danneggers Fastboot]. Er ist klein, schnell und zuverlässig. Um einen kleinen Unterschied zu machen, lautet das Passwort zum Starten nicht "Peda" sondern "FwUp", was ein kleines Problem mit sich bringt. "Peda" ist nicht nur der Spitzname vom Autor, das "a" wird zur automatischen Baudratenerkennung verwendet. Das von mir gewählte Passwort hat das nicht zu bieten. Was mir bei der Verwendung von [https://luani.de/projekte/updateloader/ UpdateLoader] aufgefallen ist: es funktioniert trotzdem. Ganz einfach, weil der Autor ein "a" voranstellt. Das funktioniert dann auch mit so gut wie allen anderen Download-Tools. ===Mit Bootloader=== Das Firmware-Update funktioniert nur bei bidirektionaler UART-Kommunikation mit dem Mikrocontroller, also bei der Variante Direkt und ADuM-Isolator. Wenn man mutig ist, kann man bei der Optokoppler-Variante R19 und R27 bestückt werden. In jedem Fall muss die Mikrocontroller-Seite mit Strom versorgt werden, also am einfachsten am Solarregler angeschlossen lassen. Berhard M. (boregard) hat das Programm [https://www.mikrocontroller.net/topic/73196#1067153 lboot] (auch im Download-Paket) geschrieben, das unter Linux mit dem schönen Fastboot von Peter Danegger spricht. Damit der Download funktioniert, muss das Pirozeda-Backend (und andere Software, die auf das UART-Interface zugreift) beendet werden. <source lang="shell"> ./bootloader -d /dev/serial0 -b 115200 -t 1024 -p pirozeda_0.2.hex -P aFwUp </source> ===Ohne Bootloader=== siehe [[#Flashen_der_Firmware]] =Einrichten der Optionen= ==HAT-ID== Wie bereits weiter oben geschrieben, ist der HAT-EEProm momentan eher ein Gimmick als wirklich genutztes Feature. Die Anwendung zur Generierung der Daten kann im [https://github.com/raspberrypi/hats/tree/master/eepromutils GitHub-Repo] vom Raspberry Pi heruntergeladen werden. Da der EEProm im normalen Betrieb schreibgeschützt ist, muss SJ1 gebrückt werden - am besten mit einem guten Klecks Lötzinn. Anschließend kann mit dem Script eepflash.sh (liegt dem Download-Paket bei) das EEProm-Image geschrieben werden: <source lang="bash"> sudo ./eepflash.sh -w -f=pirozeda-hat_id.eep -t=24c32 -a=50 </source> Aktuell sind weder Product-ID noch Version-ID vergeben, ansonsten ist die Konfiguration wie folgt: <pre> # Start of atom #0 of type 0x0001 and length 60 # Vendor info product_uuid 9edc3aef-683c-4007-b2f2-3ea4969b1737 product_id 0x0000 product_ver 0x0000 vendor "hobbyelektronik.org" # length=19 product "Pirozeda HAT v0.1" # length=17 # End of atom. CRC16=0x9a75 # Start of atom #1 of type 0x0002 and length 32 # GPIO map info gpio_drive 0 gpio_slew 0 gpio_hysteresis 0 back_power 0 # GPIO FUNCTION PULL # ---- -------- ---- setgpio 22 INPUT UP setgpio 26 OUTPUT NONE </pre> ==RTC== Die [http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-RTC/index.html Netzmafia] hat einen recht guten Artikel, wie man die hwclock bedient. Wer sich nicht einlesen will, hier im Schnelldurchlauf: Testen der RTC: <source lang="shell"> #call bash as superuser, this is needed to get the echo working properly sudo bash modprobe rtc-ds1307 echo "ds1307 0x68" > /sys/class/i2c-adapter/i2c-1/new_device #Auslesen der Uhr hwclock --debug -r exit </source> Dauerhaftes aktivieren der RTC: <source lang="shell"> sudo bash # enable module echo "# enable DS1307-RTC" >> /etc/modules echo "rtc-ds1307" >> /etc/modules # remove fake-hwclock update-rc.d -f fake-hwclock disable update-rc.d -f fake-hwclock remove apt-get remove fake-hwclock # overwrite prepared configuration of hwclock cp /etc/init.d/hwclock.sh ./hwclock.old cat ./hwclock.new > /etc/init.d/hwclock.sh # enable start/stop script update-rc.d hwclock.sh enable exit </source> Laut Anleitung von Netzmafia muss die Datei <code>/etc/init.d/hwclock.sh</code> noch wie folgt angepasst werden: <source lang="text"> Nun muss noch das Start/Stopp-Script für die RTC angepasst werden. Dazu wird (als root-User) die Datei /etc/init.d/hwclock.sh mit dem Editor bearbeitet. Zunächst tragen Sie am Anfang des Scripts die Default-Wert ein bzw. überprüfen diese: # These defaults are user-overridable in /etc/default/hwclock BADYEAR=no HWCLOCKACCESS=yes HWCLOCKPARS=' --noadjfile --utc' HCTOSYS_DEVICE=rtc0 Nach der Zeile 'case "$1" in start)' werden die folgenden drei Zeilen auskommentieren ('#' davorsetzen): #if [ -d /run/udev ] || [ -d /dev/.udev ]; then # return 0 #fi </source> Um das zu vereinfachen, habe ich eine SH-Datei vorbereitet, natürlich muss sich diese (<code>hwclock.new</code>) im gleichen Verzeichnis liegen, damit es funktioniert. Im Ordner <code>options/rtc</code> befindet sich sowohl die <code>rtc-test.sh</code> als auch <code>rtc-enable.sh</code>. Da diese über meinen Windows-PC gewandert sind und dadurch ihre Dateieigenschaften verloren haben, müssen sie entweder als ausführbar markiert werden oder mit <code>/bin/bash</code> gestartet werden: <source lang="shell"> sudo /bin/bash rtc-test.sh </source> ==I²C + Taster== Für die Verwendung des I²C muss eigentlich nur in <code>raspi-config</code> das I²C-Interface aktiviert werden. Mit der Konfiguration im ID-EEPRom wird der Taster in den Device-Tree eingebunden, allerdings kann er prinzipiell auch ohne angesprochen werden. =Backend= Das Back- und Frontend aus [[Pirozeda]] kann prinzipiell weiterverwendet werden. Es gibt allerdings noch keinen Support der neuen Features. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Verbesserungsmöglichkeiten= * Korrektur der Reset-Beschaltung * ESD-Schutz hinzufügen. Aktuell können auf den Footprints von C7, C11 und C14 ESD-Schutzdioden wie B72500D50A60 von Reichelt bestückt werden. Allerdings ist die Positionierung nicht ideal * Stiftwanne für den SPI-Schnittstelle oben auf der Leiterkarte platzieren * Die Widerstände für die Direktverbindung so platzieren, dass sie für das Bootloader-Update einfacher bestückt werden können (oder gleich Jumper) * Hinzufügen der Batteriehalter der billigen RTC-Module (Recycling FTW!) * Entfernen des nicht benötigten I²C-Levelshifters * Vermeiden von Backfeed in der Direkt-Variante =Download= [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format * Quellen des Bootloaders von Peter Dannegger * Quellen der Firmware + flashbare Images * Scripts für die Einrichtung der Optionen [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 5e19e01282a931589ded353c59dc77b12337ebac 1331 1330 2019-03-21T21:34:00Z Chris 2 size matters wikitext text/x-wiki [[Datei:Pirozeda_hat_rpizerow.jpg|300px|thumb|Pirozeda-HAT mit ADuM-Isolator auf Raspberry Pi Zero W]] Wie bereits im [[Pirozeda|Hauptartikel]] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar Geschmackssache aber in Hinblick auf Platz das Beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== '''Noch nicht aufgebaut und getestet.''' Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist, dass neben der gemeinsamen Masse mit der Solaranlage Backfeed entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Diese Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== '''Aufgebaut und erfolgreich getestet.''' Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_opto_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_opto_assy.png|Bestückungsplan mit Optokoppler pirozeda_hat_0.1_opto.jpg|Aufgebauter HAT - es passt sogar ein MJ-Quarz </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R13, R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== '''Aufgebaut und weitestgehend erfolgreich getestet.''' Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator pirozeda_hat_0.1_adum.jpg|Aufgebauter HAT mit Hotfix </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 1 || R9 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} Bei der Schaltungsentwicklung hat sich leider ein dummer Fehler eingeschlichen. Ich dachte nicht daran, dass der ADuM !RES treiben wird - und das v.a. nach GND. Kann man zwar halbwegs in Software umgehen, ist aber Mist. '''Die einfachste Fehlerbeseitigung ist, R10 einfach nicht zu bestücken.''' Der ADuM1301 ist trotz des fehlenden Features die günstigste Lösung. Der Reset des Mikrocontrollers (und damit das Wechseln in den Bootloader) kann auch per Kommando ausgelöst werden. Wer will, kann jedoch auch einen Hotfix implementieren: Dazu muss das obere Pad von R10 von der Leiterbahn getrennt werden (rot). Auf den Pads von R18 (rechts) und R10 kann nun ein BSS138 verdreht aufgesetzt werden. Das obere Pad muss dabei noch mit Masse verbunden werden (orange). <gallery> Pirozeda_hat_0.1_adum_hotfix.png Pirozeda_hat_0.1_adum_hotfix.jpg </gallery> Achtung: Auch mit diesem Hotfix gibt es einen Fallstrick: Ist die "Raspberry Pi"-Seite Stromlos, geht der Ausgangspin des ADuM auf high, folglich hängt Reset bei low (aktiv). Kann seine Vorteile haben, zum Flashen des Mikrocontrollers aber eher unpraktisch. =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== '''Aufgebaut und erfolgreich getestet.''' Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEProm ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SJ1 || || SJ || |- | 1 || C6 || 100n || C0603 || X7R-G0603 100N |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 2 || R3, R4 || 3k3 || R0603 || RND 0603 1 3,3K |} Aktuell gibt es noch keine weitere Unterstützung hierfür. Es handelt sich also eher um ein Gimmick. Den EEProm kann man sich recht günstig von eBay-Modulen "abernten" - einfach im nächsten Abschnitt weiterlesen. ==Real-Time-Clock== '''Aufgebaut und erfolgreich getestet.''' Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R11, R12 || 0 || R0603 || RND 0603 1 0 |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 2 || R6, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. Der Levelshifter kann nach ersten Testes getrost weggelassen werden. Wem der DS1307 bei Reichelt zu teuer ist, kann sich bei eBay ein Modul mit dem Chip, passendem Quarz (der zufällig dem verwendeten entspricht) und einem ebenfalls passenden EEProm besorgen. Der Batteriehalter passt im aktuellen Design leider nicht. <gallery> EBay-RTC-Module.jpg|RTC-Modul als Bauteilspender </gallery> ==Option: I²C(-OLED) + Taster== '''Noch nicht aufgebaut und getestet.''' Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |} ==Status-LEDs== '''Aufgebaut und erfolgreich getestet.''' Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 3 || R24, R25, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || LED1 || gn || CHIP-LED0603 || |- | 2 || LED2, LED3 || or || CHIP-LED0603 || |} LED1 (mitte) zeigt Aktivität an, LED2 (unten) ist mehr oder weniger die Power-LED. Mehr oder weniger, da sie beim Start der Firmware aktiviert wird (nicht aber im Bootloader). Dadurch kann man sehr schnell erkennen, ob sich die Hardware in einem Bootloop befindet. LED3 (oben) kann vom Raspberry Pi angesteuert werden. Standardmäßig sind in der <code>config.h</code> folgende Zeiten für LED1 eingestellt: * Start der Anwendung: 250 ms * Korrekt empfangene Nachrichten: 10 ms * Fehlerhaft empfangene Nachrichten: 200 ms Damit kann man auf den einen Blick erkennen, ob Daten vernünftig ankommen und verarbeitet werden können. =Aufbau der Hardware= ==Bestücken der Leiterkarte== Die Hardware kann im Prinzip in beliebiger Reihenfolge aufgebaut werden. Trotzdem ist es ratsam, die großen/hohen Bauteile zuletzt aufzulöten. Die Steckkräfte einer 2x20 Buchsenleiste sind vergleichsweise groß. Diese können reduziert werden, indem nicht verwendete Pins aus der Buchsenleiste entfernt werden. Um diese nicht wieder (fragt nicht) zurückstecken zu müssen, hier eine Auflistung der benötigten Pins: 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 15, 17, 20, 25, 27, 28, 30, 34, 37, 39. Oder einfach als Bild: <gallery> Pirozeda_hat_0.1_buchsenleiste_pins.png|benötigte Pins (blau markiert) </gallery> Der Wannenstecker lässt sich am einfachsten auflöten, wenn man die Pads auf einer Seite (egal welche) der Leiterkarte bisschen stärker verzinnt. Dadurch kann man den Konnektor ein wenig verklemmen und vor dem Verlöten besser ausrichten. ==Zuleitung== Als Zuleitung habe ich für die ersten Muster den Artikel LIYY 614 (Steuerleitung 6x0,14mm², ungeschirmt) von Reichelt verwendet. Beim Bestellen habe ich leider mehr auf den Preis als die Schirmung geachtet. In Hinblick darauf, dass der Schirm der Buchse im Regler eh nicht mit Masse verbunden ist, ist es eine ziemliche Fummelarbeit, diese mit dem Massepin zu verbinden. Erkenntnisse über die maximale Leitungslänge gibt es noch nicht. Der Vorteil dieser Leitung ist: die Adern können direkt im Pfostenverbinder verpresst werden: <gallery> Pirozeda_hat_0.1_pfosten.jpg </gallery> Ich habe mich für folgende Farbgebung entschieden, beim Pinmapping selbst gibt es keine Wahl: {| class="wikitable" ! Mini-DIN || Signal || Farbe || Wannenstecker |- | 3 || MISO || grau || 1 |- | 4 || GND || braun || 3 |- | 5 || 3V3 || rosa || 5 |- | 6 || MOSI || grün || 2 |- | 7 || SCK || gelb || 4 |- | 8 || !CS || weiß || 6 |} Beim Mini-DIN-Stecker sollte darauf geachtet werden, die äußere Hülle nicht komplett über den Rest zu stülpen, da die Buchse beim Regler ziemlich weit nach innen versetzt ist: <gallery> Pirozeda_hat_0.1_minidin.jpg </gallery> =Firmware= Grundsätzlich läuft die Firmware des Originaldesign auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel und viele neue Features fehlen: Ab 0.2: * Status-LEDs * Uptime-Counter * Messung der Versorgungsspannung * Anzeigen von Bootinformationen ** Resetgrund ** Anzahl der vorherigen Reboots ** Dauer der vorherigen Uptime ** Fusecheck ** Watchdog-Info ** Aktivierte Nachrichten * Neustart + Wechsel in den Bootloader per Kommando * Statistik über empfangene Nachrichten (optional) * Timestamps (optional, aktuell nicht kompatibel mit der Backend-Software) * Erneutes übertragen der Headerinformationen * Kann die Firmware bei einem "Katzen-Paket" miauen. Einfach nur weil. ==Konfiguration== Einige der Features müssen vor dem Kompilieren aktiviert bzw. eingestellt werden. Die Schalter und Defines hierfür befinden sich in zwei Header-Dateien: <code>config.h</code> * <code>PIROZEDA_KITTY_DEBUG</code>: Anzeigen der "Katzen-Pakete" (Vorgabe: inaktiv) * <code>PIROZEDA_TIMESTAMPS</code>: Anzeigen der Timestamps (Vorgabe: inaktiv) * <code>PIROZEDA_WDT_TIMEOUT</code>: Timeout des Watchdogs (Vorgabe: 4 s) * <code>PIROZEDA_UPTIME</code>: Führen der Uptime, abrufbar über den Befehl (Vorgabe: aktiv) * <code>PIROZEDA_SUPPLY_AVGCNT</code>: Anzahl der Messwerte für die Mittelwertbildung der Systemspannung (Vorgabe: 10, maximal: 32) * <code>PIROZEDA_HEADERCNT</code>: Anzahl der Kopfzeilen-Datensätze, die nach dem Start oder Befehl <code>header</code> angezeigt werden (Vorgabe: 200, maximal: 255) * <code>PIROZEDA_STATUS_LED_BOOT</code>: Leuchtdauer der Status-LED nach dem Start (Vorgabe: 100 -> 250 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXOK</code>: Leuchtdauer der Status-LED bei empfangenem Paket (Vorgabe: 4 -> 10 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXERR</code>: Leuchtdauer der Status-LED bei einem Fehler (Vorgabe: 80 -> 200 ms, maximal: 255) * <code>BOOTLOADER_PASSWORD</code>: "Passwort" zum Wechsel in den Bootloader (Vorgabe: "FwUp", maximal 4 Zeichen, darf keine Teilstrings von Befehlen enthalten) <code>prozeda_cfg.h</code> * <code>PROZEDA_USE_COLUMN_NAMES</code>: Verwenden der Spaltennamen (irrelevant für Pirozeda) * <code>PROZEDA_SUPPORT_DISPLAY</code>: Aktiviert den Empfang von Displaydaten (Vorgabe: aktiv) * <code>PROZEDA_SUPPORT_HEADER</code>: Aktiviert den Empfang von Kopfzeilen-Datensätzen (Vorgabe: aktiv) * <code>PROZEDA_IGNORE_KITTY</code>: Ignorieren von Katzen-Paketen, andernfalls werden Fehler ausgegeben (Vorgabe: aktiv) * <code>PROZEDA_MSG_MAXTICKS</code>: Ticks, nach denen ein Paket als abgeschlossen erkannt wird, sollte nur bei Anpassung der CPU-Frequenz angepasst werden (Vorgabe: 3) ==Befehle== Neu ist ab v0.2, dass Befehle an den Mikrocontroller gesendet werden können. Je nach Konfiguration sind dies: * <code>reset</code>: Neustart * <code>uptime</code>: Anzeige der Laufzeit * <code>bootinfo</code>: Anzeigen der Infos, die auch beim (Neu-)Start angezeigt werden * <code>header</code>: Header werden gemäß <code>PIROZEDA_HEADERCNT</code> erneut ausgegeben * <code>stats</code>: Anzeigen der Statistik über empfangene Nachrichten und Empfangsfehler Alle Befehle sind Case-sensitive. ==Flashen der Firmware== Mit den Möglichkeiten steigt die Komplexität. Dadurch dass der die Hardware für die Verwendung mit und ohne Bootloader ausgelegt ist, gibt es mehrere "Pfade" für das Flashen. Wer auf Nummer sicher gehen will, lädt einfach Bootloader und Firmware auf den Mikrocontroller herunter. Selbst wenn man "nur" die Variante mit unidirektionalem UART hat - die Brücken Versorgung und für den UART zum Mikrocontroller ist schneller gelötet als die Stiftleiste für den ISP-Port. Das Einlöten einer wahnsinnig hohen Stiftleiste kann übrigens umgangen werden, indem eine Stiftleiste in das Programmierkabel gesteckt und im Footprint der Buchse "verkeilt" wird. Wirklich keine Dauerlösung aber im Idealfall muss man es nur einmal machen. ===Über Raspberry Pi=== Zunächst muss, wenn nicht schon geschehen, über <code>sudo raspi-config</code> das SPI-Interface aktiviert (reboot nicht vergessen) und [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer#Installation_der_Compiler AVRDUDE installiert] werden. Den Regler vom HAT trennen, nicht vergessen, dass R10 oder der Hotfix entfernt werden muss, falls der ADuM-Isolator verwendet und einseitig versorgt (also nicht auf dem Raspi steckt) wird und anschließend den SPI-Port mit SV2 verbinden. {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin |- | MISO || 1 || BCM 9 || 21 |- | 3V3 || 2 || 3V3 || 17 |- | SCK || 3 || BCM 11 || 23 |- | MOSI || 4 || BCM 10 || 19 |- | !RES || 5 || BCM 25 || 22 |- | GND || 6 || GND || 20 |} ====Mit Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = FC }} Die empfohlene Variante (auch wenn man nicht beabsichtigt, den Bootloader zu nutzen). Mit Bootloader sind das folgende Befehle: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0xFC:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_fboot_0.2.hex" </source> ====Ohne Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} 'cause I ain't gonna judge you <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_0.2.hex" </source> ==Update der Firmware== In Sachen Bootloader bin ich ein großer Fan von [https://www.mikrocontroller.net/articles/AVR_Bootloader_FastBoot_von_Peter_Dannegger Peter Danneggers Fastboot]. Er ist klein, schnell und zuverlässig. Um einen kleinen Unterschied zu machen, lautet das Passwort zum Starten nicht "Peda" sondern "FwUp", was ein kleines Problem mit sich bringt. "Peda" ist nicht nur der Spitzname vom Autor, das "a" wird zur automatischen Baudratenerkennung verwendet. Das von mir gewählte Passwort hat das nicht zu bieten. Was mir bei der Verwendung von [https://luani.de/projekte/updateloader/ UpdateLoader] aufgefallen ist: es funktioniert trotzdem. Ganz einfach, weil der Autor ein "a" voranstellt. Das funktioniert dann auch mit so gut wie allen anderen Download-Tools. ===Mit Bootloader=== Das Firmware-Update funktioniert nur bei bidirektionaler UART-Kommunikation mit dem Mikrocontroller, also bei der Variante Direkt und ADuM-Isolator. Wenn man mutig ist, kann man bei der Optokoppler-Variante R19 und R27 bestückt werden. In jedem Fall muss die Mikrocontroller-Seite mit Strom versorgt werden, also am einfachsten am Solarregler angeschlossen lassen. Berhard M. (boregard) hat das Programm [https://www.mikrocontroller.net/topic/73196#1067153 lboot] (auch im Download-Paket) geschrieben, das unter Linux mit dem schönen Fastboot von Peter Danegger spricht. Damit der Download funktioniert, muss das Pirozeda-Backend (und andere Software, die auf das UART-Interface zugreift) beendet werden. <source lang="shell"> ./bootloader -d /dev/serial0 -b 115200 -t 1024 -p pirozeda_0.2.hex -P aFwUp </source> ===Ohne Bootloader=== siehe [[#Flashen_der_Firmware]] =Einrichten der Optionen= ==HAT-ID== Wie bereits weiter oben geschrieben, ist der HAT-EEProm momentan eher ein Gimmick als wirklich genutztes Feature. Die Anwendung zur Generierung der Daten kann im [https://github.com/raspberrypi/hats/tree/master/eepromutils GitHub-Repo] vom Raspberry Pi heruntergeladen werden. Da der EEProm im normalen Betrieb schreibgeschützt ist, muss SJ1 gebrückt werden - am besten mit einem guten Klecks Lötzinn. Anschließend kann mit dem Script eepflash.sh (liegt dem Download-Paket bei) das EEProm-Image geschrieben werden: <source lang="bash"> sudo ./eepflash.sh -w -f=pirozeda-hat_id.eep -t=24c32 -a=50 </source> Aktuell sind weder Product-ID noch Version-ID vergeben, ansonsten ist die Konfiguration wie folgt: <pre> # Start of atom #0 of type 0x0001 and length 60 # Vendor info product_uuid 9edc3aef-683c-4007-b2f2-3ea4969b1737 product_id 0x0000 product_ver 0x0000 vendor "hobbyelektronik.org" # length=19 product "Pirozeda HAT v0.1" # length=17 # End of atom. CRC16=0x9a75 # Start of atom #1 of type 0x0002 and length 32 # GPIO map info gpio_drive 0 gpio_slew 0 gpio_hysteresis 0 back_power 0 # GPIO FUNCTION PULL # ---- -------- ---- setgpio 22 INPUT UP setgpio 26 OUTPUT NONE </pre> ==RTC== Die [http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-RTC/index.html Netzmafia] hat einen recht guten Artikel, wie man die hwclock bedient. Wer sich nicht einlesen will, hier im Schnelldurchlauf: Testen der RTC: <source lang="shell"> #call bash as superuser, this is needed to get the echo working properly sudo bash modprobe rtc-ds1307 echo "ds1307 0x68" > /sys/class/i2c-adapter/i2c-1/new_device #Auslesen der Uhr hwclock --debug -r exit </source> Dauerhaftes aktivieren der RTC: <source lang="shell"> sudo bash # enable module echo "# enable DS1307-RTC" >> /etc/modules echo "rtc-ds1307" >> /etc/modules # remove fake-hwclock update-rc.d -f fake-hwclock disable update-rc.d -f fake-hwclock remove apt-get remove fake-hwclock # overwrite prepared configuration of hwclock cp /etc/init.d/hwclock.sh ./hwclock.old cat ./hwclock.new > /etc/init.d/hwclock.sh # enable start/stop script update-rc.d hwclock.sh enable exit </source> Laut Anleitung von Netzmafia muss die Datei <code>/etc/init.d/hwclock.sh</code> noch wie folgt angepasst werden: <source lang="text"> Nun muss noch das Start/Stopp-Script für die RTC angepasst werden. Dazu wird (als root-User) die Datei /etc/init.d/hwclock.sh mit dem Editor bearbeitet. Zunächst tragen Sie am Anfang des Scripts die Default-Wert ein bzw. überprüfen diese: # These defaults are user-overridable in /etc/default/hwclock BADYEAR=no HWCLOCKACCESS=yes HWCLOCKPARS=' --noadjfile --utc' HCTOSYS_DEVICE=rtc0 Nach der Zeile 'case "$1" in start)' werden die folgenden drei Zeilen auskommentieren ('#' davorsetzen): #if [ -d /run/udev ] || [ -d /dev/.udev ]; then # return 0 #fi </source> Um das zu vereinfachen, habe ich eine SH-Datei vorbereitet, natürlich muss sich diese (<code>hwclock.new</code>) im gleichen Verzeichnis liegen, damit es funktioniert. Im Ordner <code>options/rtc</code> befindet sich sowohl die <code>rtc-test.sh</code> als auch <code>rtc-enable.sh</code>. Da diese über meinen Windows-PC gewandert sind und dadurch ihre Dateieigenschaften verloren haben, müssen sie entweder als ausführbar markiert werden oder mit <code>/bin/bash</code> gestartet werden: <source lang="shell"> sudo /bin/bash rtc-test.sh </source> ==I²C + Taster== Für die Verwendung des I²C muss eigentlich nur in <code>raspi-config</code> das I²C-Interface aktiviert werden. Mit der Konfiguration im ID-EEPRom wird der Taster in den Device-Tree eingebunden, allerdings kann er prinzipiell auch ohne angesprochen werden. =Backend= Das Back- und Frontend aus [[Pirozeda]] kann prinzipiell weiterverwendet werden. Es gibt allerdings noch keinen Support der neuen Features. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Verbesserungsmöglichkeiten= * Korrektur der Reset-Beschaltung * ESD-Schutz hinzufügen. Aktuell können auf den Footprints von C7, C11 und C14 ESD-Schutzdioden wie B72500D50A60 von Reichelt bestückt werden. Allerdings ist die Positionierung nicht ideal * Stiftwanne für den SPI-Schnittstelle oben auf der Leiterkarte platzieren * Die Widerstände für die Direktverbindung so platzieren, dass sie für das Bootloader-Update einfacher bestückt werden können (oder gleich Jumper) * Hinzufügen der Batteriehalter der billigen RTC-Module (Recycling FTW!) * Entfernen des nicht benötigten I²C-Levelshifters * Vermeiden von Backfeed in der Direkt-Variante =Download= [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format * Quellen des Bootloaders von Peter Dannegger * Quellen der Firmware + flashbare Images * Scripts für die Einrichtung der Optionen [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 1bb1628f47d75daff9e60ea14df4c560615932f0 Datei:Pirozeda hat.zip 6 526 1323 1220 2019-03-21T21:05:43Z Chris 2 Chris lud eine neue Version von [[Datei:Pirozeda hat.zip]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Pirozeda 0 487 1325 1243 2019-03-21T21:08:04Z Chris 2 /* Download */ wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] cf592710d59f124fdb49e0d8b8c270504c31cebf 1332 1325 2019-03-30T18:38:47Z Chris 2 /* Vorbereitung */ wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== ===Vor Pirozeda 0.4=== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ===Ab Pirozeda 0.4=== Pirozeda ab 0.4 verwendet Python 3. Dementsprechend müssen die Module für die neuere Plattform installiert werden. Für JSON-RPC wird nun eine andere Lib verwendet, die zugleich "Werkzeug" als Webserver verwendet: <source lang="shell"> sudo python3 -m pip install json-rpc werkzeug pyserial </source> ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] b263789dc4c5e7c0cef15d7ff061339bd4f517ac 1333 1332 2019-03-30T18:43:13Z Chris 2 /* Installation */ wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== ===Vor Pirozeda 0.4=== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ===Ab Pirozeda 0.4=== Pirozeda ab 0.4 verwendet Python 3. Dementsprechend müssen die Module für die neuere Plattform installiert werden. Für JSON-RPC wird nun eine andere Lib verwendet, die zugleich "Werkzeug" als Webserver verwendet: <source lang="shell"> sudo python3 -m pip install json-rpc werkzeug pyserial </source> ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. ===Vor Pirozeda 0.4=== Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ===Ab Pirozeda 0.4=== Ab Pirozeda 0.4 kann das Script als [http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/ Service] ausgeführt werden. Das entsprechende Script ist für die Verwendung in <code>/home/pi/pirozeda</code> vorbereitet und kann einfach wie folgt installiert werden: <source lang="shell"> sudo cp pirozeda.sh /etc/init.d sudo chmod +x /etc/init.d/pirozeda.sh sudo update-rc.d pirozeda.sh defaults sudo /etc/init.d/pirozeda start </source> Wer Pirozeda woanders installieren möchte, kann das Shellscript jederzeit entsprechend anpassen. Auch die Verwendung von cron ist natürlich weiterhin möglich, allerdings muss nun python3 verwendet werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] d0dec49159d504e4698e71ad68777797c2e55a32 1335 1333 2019-03-30T18:47:16Z Chris 2 /* Download */ wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== ===Vor Pirozeda 0.4=== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ===Ab Pirozeda 0.4=== Pirozeda ab 0.4 verwendet Python 3. Dementsprechend müssen die Module für die neuere Plattform installiert werden. Für JSON-RPC wird nun eine andere Lib verwendet, die zugleich "Werkzeug" als Webserver verwendet: <source lang="shell"> sudo python3 -m pip install json-rpc werkzeug pyserial </source> ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. ===Vor Pirozeda 0.4=== Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ===Ab Pirozeda 0.4=== Ab Pirozeda 0.4 kann das Script als [http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/ Service] ausgeführt werden. Das entsprechende Script ist für die Verwendung in <code>/home/pi/pirozeda</code> vorbereitet und kann einfach wie folgt installiert werden: <source lang="shell"> sudo cp pirozeda.sh /etc/init.d sudo chmod +x /etc/init.d/pirozeda.sh sudo update-rc.d pirozeda.sh defaults sudo /etc/init.d/pirozeda start </source> Wer Pirozeda woanders installieren möchte, kann das Shellscript jederzeit entsprechend anpassen. Auch die Verwendung von cron ist natürlich weiterhin möglich, allerdings muss nun python3 verwendet werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= ==Vor Pirozeda 0.4== [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Ab Pirozeda 0.4== [[Datei:Pirozeda rpi.zip]] enthält: * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) === 2019-03-30: Version 0.4 === * Umstellung Auf Python 3 * Script kann nun als Service verwendet werden * Fehlerkorrektur Anzeige von Volumenstrom * Mehr Informationen von der Firmware (Version/Build/Reglerversion/...) Ich habe leider keine Vergleichsdaten aber mir scheint die CPU-Last auf dem Pi bei aktivem Frontend sehr hoch, kann das jemand bestätigen? [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] aa0318be77183789dfb56e68f7f8af9b346bb5d4 1336 1335 2019-04-14T20:38:47Z Chris 2 /* Ab Pirozeda 0.4 */ Typo korrigiert wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== ===Vor Pirozeda 0.4=== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ===Ab Pirozeda 0.4=== Pirozeda ab 0.4 verwendet Python 3. Dementsprechend müssen die Module für die neuere Plattform installiert werden. Für JSON-RPC wird nun eine andere Lib verwendet, die zugleich "Werkzeug" als Webserver verwendet: <source lang="shell"> sudo python3 -m pip install json-rpc werkzeug pyserial </source> ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. ===Vor Pirozeda 0.4=== Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ===Ab Pirozeda 0.4=== Ab Pirozeda 0.4 kann das Script als [http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/ Service] ausgeführt werden. Das entsprechende Script ist für die Verwendung in <code>/home/pi/pirozeda</code> vorbereitet und kann einfach wie folgt installiert werden: <source lang="shell"> sudo cp pirozeda.sh /etc/init.d sudo chmod +x /etc/init.d/pirozeda.sh sudo update-rc.d pirozeda.sh defaults sudo /etc/init.d/pirozeda.sh start </source> Wer Pirozeda woanders installieren möchte, kann das Shellscript jederzeit entsprechend anpassen. Auch die Verwendung von cron ist natürlich weiterhin möglich, allerdings muss nun python3 verwendet werden. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= ==Vor Pirozeda 0.4== [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Ab Pirozeda 0.4== [[Datei:Pirozeda rpi.zip]] enthält: * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) === 2019-03-30: Version 0.4 === * Umstellung Auf Python 3 * Script kann nun als Service verwendet werden * Fehlerkorrektur Anzeige von Volumenstrom * Mehr Informationen von der Firmware (Version/Build/Reglerversion/...) Ich habe leider keine Vergleichsdaten aber mir scheint die CPU-Last auf dem Pi bei aktivem Frontend sehr hoch, kann das jemand bestätigen? [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 2729851b35cfa76bb5f32118ec79cc42b906f0ab 1337 1336 2019-04-21T19:28:27Z Chris 2 /* Ab Pirozeda 0.4 */ pirozeda.py muss ausführbar sein wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== ===Vor Pirozeda 0.4=== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ===Ab Pirozeda 0.4=== Pirozeda ab 0.4 verwendet Python 3. Dementsprechend müssen die Module für die neuere Plattform installiert werden. Für JSON-RPC wird nun eine andere Lib verwendet, die zugleich "Werkzeug" als Webserver verwendet: <source lang="shell"> sudo python3 -m pip install json-rpc werkzeug pyserial </source> ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. ===Vor Pirozeda 0.4=== Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ===Ab Pirozeda 0.4=== Ab Pirozeda 0.4 kann das Script als [http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/ Service] ausgeführt werden. Das entsprechende Script ist für die Verwendung in <code>/home/pi/pirozeda</code> vorbereitet und kann einfach wie folgt installiert werden: <source lang="shell"> sudo chmod +x pirozeda.py sudo cp pirozeda.sh /etc/init.d sudo chmod +x /etc/init.d/pirozeda.sh sudo update-rc.d pirozeda.sh defaults sudo /etc/init.d/pirozeda.sh start </source> Wer Pirozeda woanders installieren möchte, kann das Shellscript jederzeit entsprechend anpassen. Auch die Verwendung von cron ist natürlich weiterhin möglich, allerdings muss nun python3 verwendet werden. Update 21.04.2019: <code>pirozeda.py</code> muss für die Verwendung der Shell-Datei ebenfalls als ausführbar markiert sein. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= ==Vor Pirozeda 0.4== [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Ab Pirozeda 0.4== [[Datei:Pirozeda rpi.zip]] enthält: * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) === 2019-03-30: Version 0.4 === * Umstellung Auf Python 3 * Script kann nun als Service verwendet werden * Fehlerkorrektur Anzeige von Volumenstrom * Mehr Informationen von der Firmware (Version/Build/Reglerversion/...) Ich habe leider keine Vergleichsdaten aber mir scheint die CPU-Last auf dem Pi bei aktivem Frontend sehr hoch, kann das jemand bestätigen? [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 3e87914630fc866d3ebca948d2120aa552bdd41d 1338 1337 2019-04-30T20:27:04Z Chris 2 /* Vorbereitung */ Missverständliche Beschreibung korrigiert wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht entweder über <code>sudo raspi-config</code> (keine Konsole aber UART aktiv) oder in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. ===Vor Pirozeda 0.4=== Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ===Ab Pirozeda 0.4=== Pirozeda ab 0.4 verwendet Python 3. Dementsprechend müssen die Module für die neuere Plattform installiert werden. Für JSON-RPC wird nun eine andere Lib verwendet, die zugleich "Werkzeug" als Webserver verwendet: <source lang="shell"> sudo python3 -m pip install json-rpc werkzeug pyserial </source> Auch hier kann über <code>miniterm</code> geprüft werden, ob Daten ankommen. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. ===Vor Pirozeda 0.4=== Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ===Ab Pirozeda 0.4=== Ab Pirozeda 0.4 kann das Script als [http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/ Service] ausgeführt werden. Das entsprechende Script ist für die Verwendung in <code>/home/pi/pirozeda</code> vorbereitet und kann einfach wie folgt installiert werden: <source lang="shell"> sudo chmod +x pirozeda.py sudo cp pirozeda.sh /etc/init.d sudo chmod +x /etc/init.d/pirozeda.sh sudo update-rc.d pirozeda.sh defaults sudo /etc/init.d/pirozeda.sh start </source> Wer Pirozeda woanders installieren möchte, kann das Shellscript jederzeit entsprechend anpassen. Auch die Verwendung von cron ist natürlich weiterhin möglich, allerdings muss nun python3 verwendet werden. Update 21.04.2019: <code>pirozeda.py</code> muss für die Verwendung der Shell-Datei ebenfalls als ausführbar markiert sein. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= ==Vor Pirozeda 0.4== [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Ab Pirozeda 0.4== [[Datei:Pirozeda rpi.zip]] enthält: * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) === 2019-03-30: Version 0.4 === * Umstellung Auf Python 3 * Script kann nun als Service verwendet werden * Fehlerkorrektur Anzeige von Volumenstrom * Mehr Informationen von der Firmware (Version/Build/Reglerversion/...) Ich habe leider keine Vergleichsdaten aber mir scheint die CPU-Last auf dem Pi bei aktivem Frontend sehr hoch, kann das jemand bestätigen? [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 05987669564961d8cc89eb0d17f6e06293d61a7d Datei:Pirozeda hat rpizerow.jpg 6 579 1329 2019-03-21T21:32:05Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Pirozeda rpi.zip 6 580 1334 2019-03-30T18:43:41Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Atmelice adapter.jpg 6 581 1340 2019-05-07T20:30:37Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Atmelice assy bot.png 6 582 1341 2019-05-07T20:30:48Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Atmelice assy top.png 6 583 1342 2019-05-07T20:31:02Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Atmelice jtagadapter.jpg 6 584 1343 2019-05-07T20:31:21Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Atmelice sch.png 6 585 1344 2019-05-07T20:31:37Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Atmel-ICE-Adapter 0 586 1345 2019-05-07T20:33:05Z Chris 2 Seite erstellt wikitext text/x-wiki Über die Zeit haben sich doch ein paar AVR-Programmer angesammelt: der [[AVR-Doper]], ein AVR-Dragon (mit dem ich gar nicht grün wurde), ein Diamex ALL-AVR und schlussendlich ein Atmel ICE. Bis zum ICE war die Verwendung aller Programmer gleich: Stiftwanne auf dem Programmer, Leitung dran und gut. Beim Doper und ALL-AVR konnte man zugleich auch noch das Target versorgen - super! =Problem= Beim ICE ist der Anschluss eher fummelig - ein filigranes Flachbandkabel im 1,27 mm-Rastermaß, am Ende ist ein 6-poliger 2,54 mm-Stecker. Für 1,27 mm liegt ein kleines Adapter-Board bei, das in anderer Hinsicht (IMHO) verdammt gefährlich ist: es gibt eine 10-polige Buchsenleiste an der AVR steht, allerdings mit JTAG dahinter. <gallery> atmelice_jtagadapter.jpg|Die 10-polige Buchsenleiste ist nur für JTAG, nicht SPI </gallery> Zumindest ich war so blöd und habe damit versucht über SPI zu programmieren. Das Target blieb aus Gründen dunkel, kaputt gegangen ist glücklicherweise nichts. Die Buchse ist nämlich nur für JTAG, nicht für SPI. Der JTAGICE in der Arbeit erlitt nach 4 Jahren einen Leitungsbruch, bei dem eindrähtigen Flachbandkabel eigentlich auch kein Wunder. Warum Atmel/Microchip sich für diese winzigen Konnektoren entschieden hat, bleibt mir ein Rätsel, der Footprint eines (bzw. zweier) ".1 inch Header" wäre kaum größer. Wenn man mal schaut, wie man an diese Konnektoren kommt und wieviel sie kosten, sollte man sich festhalten. Mit ziemlich viel Geduld und Popelei ließ sich die Buchsenleiste neu verpressen, nochmal möchte ich das allerdings nicht machen. =Idee= Deshalb sollte eine Lösung zumindest für meine Probleme her: * Buchsenleisten für 6er und 10er SPI-Interface * Möglichst wenig Stress auf das Mini-Flachbandkabel * Versorgung des Targets möglich =Lösung= [[Datei:Atmelice_adapter.jpg|300px|thumb|Atmel-ICE mit aufgeklebtem Adapter]] Eine kleine Leiterkarte, die auf den Programmer geklebt werden kann, eine (leider eher unpraktische) eigene Versorgung hat und die gewünschten Buchsenleisten. Für die Spannung kann zwischen "Feedthrough" vom USB und dem kleinen einstellbaren Linearregler, der bis zu 150 mA kann. Eine LED mit zeigt an, ob das Target versorgt wird (ok, macht der ICE im Prinzip auch): <gallery> atmelice_sch.png|Schaltplan des Adapters atmelice_assy_top.png|Bestückungsplan oben atmelice_assy_bot.png|Ansicht von unten </gallery> Um die Pinbelegung der Wannenstecker nicht nachschlagen zu müssen, ist sie in Kurzform aufgedruckt (auf Layer _tsilk und _bsilk). die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV5 || || MA05-2_127_SMD || SL 2X10G SMD1,27 |- | 1 || SV2 || || ML10 || WSL 10G |- | 1 || SV1 || || ML6 || WSL 6G |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R17 || 10k || S64Y || 64Y-10K |- | 1 || C7 || 1u || C0805 || X7R-G0805 1,0/16 |- | 2 || R2, R9 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || R1 || 470 || R0603 || RND 0603 1 470 |- | 1 || C6 || 4u7 10V || C0603 || KEM X5R0603 4,7U |- | 1 || T1 || BC848 || SOT23 || BC 848A SMD |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || X1 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || TPS76301 || SOT23-DBV || TPS 76301 DBVR |- | 1 || LED1 || red || CHIP-LED0603 || OSO LSQ971 |} Da die Pinbelegung des AVR-Ports des Atmel-ICE der des JTAGICE3 m. W. entspricht, dürfte der Adapter kompatibel sein. Habe es aber noch nicht getestet, daher ohne Garantie. =Fehler/Verbesserungspotenzial= * Durch das falsche Symbol im Schaltplan (noch vorhanden) liegt der high-active Enable auf Masse. Ist im Schaltplan korrigiert, für die Leiterkarte braucht's ein Skalpell und Fädeldraht. * Besserer Footprint für die USB-Buchse * Statt des Jumpers wäre ein Ein-Aus-Ein-Schalter (z. B. "SS 25139 NH" von Reichelt) besser * Wenn schon USB-Buchse, dann mit Funktion: ** Messung von Spannung und Strom des Targets (warum nicht auch mit Display?) ** Reset per Kommando ** UART-Interface * Buchse für JTAG (ist wirklich nur aus Platzgründen rausgeflogen) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:atmelice.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:AVR]] [[Kategorie:Kleine Helferlein]] [[Kategorie:Elektronik]] 940906ec5b5d8b7950550a289d1d9f1d24bac4a9 Datei:Atmelice-adapter.zip 6 587 1346 2019-05-07T20:33:46Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Atmel-ICE-Adapter 0 586 1347 1345 2019-05-07T20:34:09Z Chris 2 Dateiname für Download korrigiert wikitext text/x-wiki Über die Zeit haben sich doch ein paar AVR-Programmer angesammelt: der [[AVR-Doper]], ein AVR-Dragon (mit dem ich gar nicht grün wurde), ein Diamex ALL-AVR und schlussendlich ein Atmel ICE. Bis zum ICE war die Verwendung aller Programmer gleich: Stiftwanne auf dem Programmer, Leitung dran und gut. Beim Doper und ALL-AVR konnte man zugleich auch noch das Target versorgen - super! =Problem= Beim ICE ist der Anschluss eher fummelig - ein filigranes Flachbandkabel im 1,27 mm-Rastermaß, am Ende ist ein 6-poliger 2,54 mm-Stecker. Für 1,27 mm liegt ein kleines Adapter-Board bei, das in anderer Hinsicht (IMHO) verdammt gefährlich ist: es gibt eine 10-polige Buchsenleiste an der AVR steht, allerdings mit JTAG dahinter. <gallery> atmelice_jtagadapter.jpg|Die 10-polige Buchsenleiste ist nur für JTAG, nicht SPI </gallery> Zumindest ich war so blöd und habe damit versucht über SPI zu programmieren. Das Target blieb aus Gründen dunkel, kaputt gegangen ist glücklicherweise nichts. Die Buchse ist nämlich nur für JTAG, nicht für SPI. Der JTAGICE in der Arbeit erlitt nach 4 Jahren einen Leitungsbruch, bei dem eindrähtigen Flachbandkabel eigentlich auch kein Wunder. Warum Atmel/Microchip sich für diese winzigen Konnektoren entschieden hat, bleibt mir ein Rätsel, der Footprint eines (bzw. zweier) ".1 inch Header" wäre kaum größer. Wenn man mal schaut, wie man an diese Konnektoren kommt und wieviel sie kosten, sollte man sich festhalten. Mit ziemlich viel Geduld und Popelei ließ sich die Buchsenleiste neu verpressen, nochmal möchte ich das allerdings nicht machen. =Idee= Deshalb sollte eine Lösung zumindest für meine Probleme her: * Buchsenleisten für 6er und 10er SPI-Interface * Möglichst wenig Stress auf das Mini-Flachbandkabel * Versorgung des Targets möglich =Lösung= [[Datei:Atmelice_adapter.jpg|300px|thumb|Atmel-ICE mit aufgeklebtem Adapter]] Eine kleine Leiterkarte, die auf den Programmer geklebt werden kann, eine (leider eher unpraktische) eigene Versorgung hat und die gewünschten Buchsenleisten. Für die Spannung kann zwischen "Feedthrough" vom USB und dem kleinen einstellbaren Linearregler, der bis zu 150 mA kann. Eine LED mit zeigt an, ob das Target versorgt wird (ok, macht der ICE im Prinzip auch): <gallery> atmelice_sch.png|Schaltplan des Adapters atmelice_assy_top.png|Bestückungsplan oben atmelice_assy_bot.png|Ansicht von unten </gallery> Um die Pinbelegung der Wannenstecker nicht nachschlagen zu müssen, ist sie in Kurzform aufgedruckt (auf Layer _tsilk und _bsilk). die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV5 || || MA05-2_127_SMD || SL 2X10G SMD1,27 |- | 1 || SV2 || || ML10 || WSL 10G |- | 1 || SV1 || || ML6 || WSL 6G |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R17 || 10k || S64Y || 64Y-10K |- | 1 || C7 || 1u || C0805 || X7R-G0805 1,0/16 |- | 2 || R2, R9 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || R1 || 470 || R0603 || RND 0603 1 470 |- | 1 || C6 || 4u7 10V || C0603 || KEM X5R0603 4,7U |- | 1 || T1 || BC848 || SOT23 || BC 848A SMD |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || X1 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || TPS76301 || SOT23-DBV || TPS 76301 DBVR |- | 1 || LED1 || red || CHIP-LED0603 || OSO LSQ971 |} Da die Pinbelegung des AVR-Ports des Atmel-ICE der des JTAGICE3 m. W. entspricht, dürfte der Adapter kompatibel sein. Habe es aber noch nicht getestet, daher ohne Garantie. =Fehler/Verbesserungspotenzial= * Durch das falsche Symbol im Schaltplan (noch vorhanden) liegt der high-active Enable auf Masse. Ist im Schaltplan korrigiert, für die Leiterkarte braucht's ein Skalpell und Fädeldraht. * Besserer Footprint für die USB-Buchse * Statt des Jumpers wäre ein Ein-Aus-Ein-Schalter (z. B. "SS 25139 NH" von Reichelt) besser * Wenn schon USB-Buchse, dann mit Funktion: ** Messung von Spannung und Strom des Targets (warum nicht auch mit Display?) ** Reset per Kommando ** UART-Interface * Buchse für JTAG (ist wirklich nur aus Platzgründen rausgeflogen) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= [[Datei:Atmelice-adapter.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:AVR]] [[Kategorie:Kleine Helferlein]] [[Kategorie:Elektronik]] 947cb5dfb2f837926f4fb572176b4766243749dc Hauptseite 0 1 1348 1326 2019-05-07T20:34:59Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren 666d6954f72b3f7f7d5be2de5edd8e9ed1cdc918 1355 1348 2019-09-17T20:28:16Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC 11400ce5421f3911db3783402588609c8d891524 1362 1355 2019-11-10T16:32:25Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *10.11.2019 Für den VBus-Adapter Nano gibt es nun einern [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt 8359af039ce62d704b0960bceca65b82bb016c44 1363 1362 2019-11-10T16:33:00Z Chris 2 /* Neues & Änderungen */ Typo wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt d7fcdcee90bd7f9dd3879c75d6df9d9ecddd0cbc 1370 1363 2019-12-16T21:24:55Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *16.12.2019 Ein paar [[Softwaretools|Tools]] um die serielle Schnittstelle zu bespaßen und Daten aus Saleae Logic komfortabler verarbeiten zu können *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. b092dafcff55a83de9d8cec097cc30da65cdaefb 1371 1370 2019-12-16T21:26:07Z Chris 2 /* Neues & Änderungen */ Deeplinks wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. 3fbcf151163d23824783e9edd7bd7b2be7c2a6f8 1379 1371 2019-12-25T19:25:42Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] 8e8b65e518c1a2a3a2e4d6a93575d234eb8e2ef4 1388 1379 2020-01-13T18:45:07Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON be5d33a9bb394c0e3522558d3f06f61fc0c44371 1393 1388 2020-01-19T20:22:13Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) 1c1c54c4fcc8071e785e2f386d4b57873a2232d0 VBus-Decoder 0 120 1349 1339 2019-05-12T12:05:53Z Chris 2 /* VBus-Adapter Nano */ Hinweis zu Betrieb an 3,3V und Kostenersparnis dank günstigerem Regler wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> Ich sollte die untenstehende [[#Messung]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 34e0dd81c8523e38059795381205c9c2ee004401 1350 1349 2019-05-12T12:06:46Z Chris 2 /* VBus-Adapter Nano */ Wortwahl korrigiert wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 3081f6d5754099f2d9804c1eccf629e6418cb5d1 1358 1350 2019-11-10T16:24:05Z Chris 2 Nachtrag zur Komponentenwahl, Troubleshooting wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Troubleshooting== Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren * Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) * Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. * Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ** Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ** Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen * Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) * Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. * Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. * Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. * Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. * Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. * Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. * Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ** Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ** Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 145df25f4226df883359fa5f291db3e97c695e3b 1359 1358 2019-11-10T16:25:21Z Chris 2 /* Troubleshooting */ Listentyp wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Troubleshooting== Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] c87f36828bf283929746cc8df02e403629e8616d 1361 1359 2019-11-10T16:30:37Z Chris 2 Python-Implementierung wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Troubleshooting== Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. ==Leiterkarten== Es liegen noch ein paar Leiterkarten herum. Wer eine möchte, kann sich gerne bei mir melden. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Python-Implementierung= Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie und Gewährleistung: * [[Datei:VBus-Python.zip]] =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 9235498eff5b3cf9341184ce5c4349eb5f022850 1364 1361 2019-12-10T19:39:51Z Chris 2 /* Leiterkarten */ Lager leer wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Troubleshooting== Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. ==Leiterkarten== Aktuell gibt es keine Leiterkarten mehr. Wenn beim nächsten Panel noch Platz ist, gibt es wieder welche. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Python-Implementierung= Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie und Gewährleistung: * [[Datei:VBus-Python.zip]] =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 15e98f400f5e83a80eec36c924e19fbb76e287db Datei:Mcp22xx cs.zip 6 588 1351 2019-09-17T20:07:18Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 MCP-USB-Bridge 0 514 1352 1209 2019-09-17T20:25:16Z Chris 2 C#-Lib wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. Deshalb: es wird eine Version 2 geben. =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =C#-Lib= Um auch aus C# heraus und nicht (wie mit der Lib von Microchip) an ein .NET-Framework gebunden zu sein, habe ich auch eine Bibliothek sowohl für den MCP2221 als auch MCP2210 in nativem C# (ohne externe DLLs oder sonstige Abhängigkeiten) geschrieben. Einige, für den täglichen Bedarf weniger benötigte, Funktionen wurden ausgelassen; die Performance ist zumindest bei I²C ähnlich gut wie die der Python-Lib. Codebeispiele und entsprechende Anwendungen werden folgen, sobald ich Zeit habe, sie zu vervollständigen. Folgende Demos ist aktuell vorbereitet (oder geplant): * MCP2221 ** ADC/(DAC) ** TI INA219 - Current Shunt & Power Monitor ** (TI INA3221 - 3Ch Current Shunt & Power Monitor) ** Microchip MCP4725 - 12-Bit-DAC ** QMC5883L - Magnetometer ** (STM LSM-irgendwas - 6D-Sensor mit Schrittzähler) ** (Atmel/Microchip Maxtouch-Touchcontroller) ** (Avago/Broadcomm APDS-99x0 - Ambient light/Gesten-/Farb-Sensor) * MCP2210 ** Maxim MAX31855 - K-Typ Temperatursensor ** Maxim MAX7219 - LED-Treiber ** Nordic Semi nRF24L01+ - 2,4 GHz Transceiver (+ [https://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/ BLE-Hack], der Logitech-Hack ist aktuell nicht geplant) ** (TI CC1101 - Low-Power Sub-1 GHz RF Transceiver) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= [[Datei:mcp22xx_py.zip]] Python-Lib v0.1, aktuell nur für MCP2221, mit Beispielen [[Datei:Mcp22xx cs.zip]] C#-Lib v0.1, für MCP2221 und MCP2210, aktuell noch ohne Beispiele und teilweise ungetestet [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 779695e2cb80e94fd39bf45f4f49525d9c5a4dba 1353 1352 2019-09-17T20:26:26Z Chris 2 /* C#-Lib */ Begründung wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. Deshalb: es wird eine Version 2 geben. =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =C#-Lib= Um auch aus C# heraus und nicht (wie mit der Lib von Microchip) an ein .NET-Framework gebunden zu sein, habe ich auch eine Bibliothek sowohl für den MCP2221 als auch MCP2210 in nativem C# (ohne externe DLLs oder sonstige Abhängigkeiten) geschrieben. Einige, für den täglichen Bedarf weniger benötigte, Funktionen wurden ausgelassen; die Performance ist zumindest bei I²C ähnlich gut wie die der Python-Lib. Codebeispiele und entsprechende Anwendungen werden folgen, sobald ich Zeit habe, sie zu vervollständigen. Der unvollständige "Release" ist einfach nur, damit der Code unter die Leute gemischt wird :) Folgende Demos ist aktuell vorbereitet (oder geplant): * MCP2221 ** ADC/(DAC) ** TI INA219 - Current Shunt & Power Monitor ** (TI INA3221 - 3Ch Current Shunt & Power Monitor) ** Microchip MCP4725 - 12-Bit-DAC ** QMC5883L - Magnetometer ** (STM LSM-irgendwas - 6D-Sensor mit Schrittzähler) ** (Atmel/Microchip Maxtouch-Touchcontroller) ** (Avago/Broadcomm APDS-99x0 - Ambient light/Gesten-/Farb-Sensor) * MCP2210 ** Maxim MAX31855 - K-Typ Temperatursensor ** Maxim MAX7219 - LED-Treiber ** Nordic Semi nRF24L01+ - 2,4 GHz Transceiver (+ [https://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/ BLE-Hack], der Logitech-Hack ist aktuell nicht geplant) ** (TI CC1101 - Low-Power Sub-1 GHz RF Transceiver) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= [[Datei:mcp22xx_py.zip]] Python-Lib v0.1, aktuell nur für MCP2221, mit Beispielen [[Datei:Mcp22xx cs.zip]] C#-Lib v0.1, für MCP2221 und MCP2210, aktuell noch ohne Beispiele und teilweise ungetestet [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 35bcd46bbd195dea0edcd8dcae90633c26087672 1354 1353 2019-09-17T20:26:52Z Chris 2 /* Downloads */ Zeilenumbruch wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. Deshalb: es wird eine Version 2 geben. =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =C#-Lib= Um auch aus C# heraus und nicht (wie mit der Lib von Microchip) an ein .NET-Framework gebunden zu sein, habe ich auch eine Bibliothek sowohl für den MCP2221 als auch MCP2210 in nativem C# (ohne externe DLLs oder sonstige Abhängigkeiten) geschrieben. Einige, für den täglichen Bedarf weniger benötigte, Funktionen wurden ausgelassen; die Performance ist zumindest bei I²C ähnlich gut wie die der Python-Lib. Codebeispiele und entsprechende Anwendungen werden folgen, sobald ich Zeit habe, sie zu vervollständigen. Der unvollständige "Release" ist einfach nur, damit der Code unter die Leute gemischt wird :) Folgende Demos ist aktuell vorbereitet (oder geplant): * MCP2221 ** ADC/(DAC) ** TI INA219 - Current Shunt & Power Monitor ** (TI INA3221 - 3Ch Current Shunt & Power Monitor) ** Microchip MCP4725 - 12-Bit-DAC ** QMC5883L - Magnetometer ** (STM LSM-irgendwas - 6D-Sensor mit Schrittzähler) ** (Atmel/Microchip Maxtouch-Touchcontroller) ** (Avago/Broadcomm APDS-99x0 - Ambient light/Gesten-/Farb-Sensor) * MCP2210 ** Maxim MAX31855 - K-Typ Temperatursensor ** Maxim MAX7219 - LED-Treiber ** Nordic Semi nRF24L01+ - 2,4 GHz Transceiver (+ [https://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/ BLE-Hack], der Logitech-Hack ist aktuell nicht geplant) ** (TI CC1101 - Low-Power Sub-1 GHz RF Transceiver) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= [[Datei:mcp22xx_py.zip]] Python-Lib v0.1, aktuell nur für MCP2221, mit Beispielen [[Datei:Mcp22xx cs.zip]] C#-Lib v0.1, für MCP2221 und MCP2210, aktuell noch ohne Beispiele und teilweise ungetestet [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 0df7e8878df0a467c33a17178afac68db8d75c3b 1387 1354 2020-01-13T18:42:29Z Chris 2 Backplate wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. Deshalb: es wird eine Version 2 geben. =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =C#-Lib= Um auch aus C# heraus und nicht (wie mit der Lib von Microchip) an ein .NET-Framework gebunden zu sein, habe ich auch eine Bibliothek sowohl für den MCP2221 als auch MCP2210 in nativem C# (ohne externe DLLs oder sonstige Abhängigkeiten) geschrieben. Einige, für den täglichen Bedarf weniger benötigte, Funktionen wurden ausgelassen; die Performance ist zumindest bei I²C ähnlich gut wie die der Python-Lib. Codebeispiele und entsprechende Anwendungen werden folgen, sobald ich Zeit habe, sie zu vervollständigen. Der unvollständige "Release" ist einfach nur, damit der Code unter die Leute gemischt wird :) Folgende Demos ist aktuell vorbereitet (oder geplant): * MCP2221 ** ADC/(DAC) ** TI INA219 - Current Shunt & Power Monitor ** (TI INA3221 - 3Ch Current Shunt & Power Monitor) ** Microchip MCP4725 - 12-Bit-DAC ** QMC5883L - Magnetometer ** (STM LSM-irgendwas - 6D-Sensor mit Schrittzähler) ** (Atmel/Microchip Maxtouch-Touchcontroller) ** (Avago/Broadcomm APDS-99x0 - Ambient light/Gesten-/Farb-Sensor) * MCP2210 ** Maxim MAX31855 - K-Typ Temperatursensor ** Maxim MAX7219 - LED-Treiber ** Nordic Semi nRF24L01+ - 2,4 GHz Transceiver (+ [https://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/ BLE-Hack], der Logitech-Hack ist aktuell nicht geplant) ** (TI CC1101 - Low-Power Sub-1 GHz RF Transceiver) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Backplate= Im [[3D-Druck-Sammelsurium]] gibt es Backplates zum Selberdrucken =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= [[Datei:mcp22xx_py.zip]] Python-Lib v0.1, aktuell nur für MCP2221, mit Beispielen [[Datei:Mcp22xx cs.zip]] C#-Lib v0.1, für MCP2221 und MCP2210, aktuell noch ohne Beispiele und teilweise ungetestet [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 56e98286863d156938c96abe66eae5a12872173a 1390 1387 2020-01-19T20:07:37Z Chris 2 /* Downloads */ wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. Deshalb: es wird eine Version 2 geben. =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =C#-Lib= Um auch aus C# heraus und nicht (wie mit der Lib von Microchip) an ein .NET-Framework gebunden zu sein, habe ich auch eine Bibliothek sowohl für den MCP2221 als auch MCP2210 in nativem C# (ohne externe DLLs oder sonstige Abhängigkeiten) geschrieben. Einige, für den täglichen Bedarf weniger benötigte, Funktionen wurden ausgelassen; die Performance ist zumindest bei I²C ähnlich gut wie die der Python-Lib. Codebeispiele und entsprechende Anwendungen werden folgen, sobald ich Zeit habe, sie zu vervollständigen. Der unvollständige "Release" ist einfach nur, damit der Code unter die Leute gemischt wird :) Folgende Demos ist aktuell vorbereitet (oder geplant): * MCP2221 ** ADC/(DAC) ** TI INA219 - Current Shunt & Power Monitor ** (TI INA3221 - 3Ch Current Shunt & Power Monitor) ** Microchip MCP4725 - 12-Bit-DAC ** QMC5883L - Magnetometer ** (STM LSM-irgendwas - 6D-Sensor mit Schrittzähler) ** (Atmel/Microchip Maxtouch-Touchcontroller) ** (Avago/Broadcomm APDS-99x0 - Ambient light/Gesten-/Farb-Sensor) * MCP2210 ** Maxim MAX31855 - K-Typ Temperatursensor ** Maxim MAX7219 - LED-Treiber ** Nordic Semi nRF24L01+ - 2,4 GHz Transceiver (+ [https://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/ BLE-Hack], der Logitech-Hack ist aktuell nicht geplant) ** (TI CC1101 - Low-Power Sub-1 GHz RF Transceiver) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Backplate= Im [[3D-Druck-Sammelsurium]] gibt es Backplates zum Selberdrucken =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= [[Datei:mcp22xx_py.zip]] Python3-Lib v0.2, aktuell nur für MCP2221, mit Beispielen [[Datei:Mcp22xx cs.zip]] C#-Lib v0.1, für MCP2221 und MCP2210, aktuell noch ohne Beispiele und teilweise ungetestet [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 26b798489b738ff1183761a66ce1fae6580b1d0a 1391 1390 2020-01-19T20:16:53Z Chris 2 /* Anmerkungen */ Fehler im Datenblatt wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. Deshalb: es wird eine Version 2 geben. Das Datenblatt des MCP2221 enthält ein paar Fehler bzw. fehlen Informationen: * Die Berechnung der I²C-Clock ist eher ungenau * Es fehlen wichtige Informationen zu den Zuständen der Statemachines, die Microchip auch auf Rückfrage nicht herausrücken wollte, für die Implementierung aber zwingend erforderlich sind. Hier musste ich mutmaßen * Im Befehl zum Setzen der SRAM-Settings ist der angegebene Wert zum Schreiben der GPIO-Settings (Byte 7) falsch * Das Umstellen der ADC-Referenz muss nach dem Setzen der Pinfunktion erfolgen, da sonst die Referenz auf den Default-Wert gesetzt werden =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =C#-Lib= Um auch aus C# heraus und nicht (wie mit der Lib von Microchip) an ein .NET-Framework gebunden zu sein, habe ich auch eine Bibliothek sowohl für den MCP2221 als auch MCP2210 in nativem C# (ohne externe DLLs oder sonstige Abhängigkeiten) geschrieben. Einige, für den täglichen Bedarf weniger benötigte, Funktionen wurden ausgelassen; die Performance ist zumindest bei I²C ähnlich gut wie die der Python-Lib. Codebeispiele und entsprechende Anwendungen werden folgen, sobald ich Zeit habe, sie zu vervollständigen. Der unvollständige "Release" ist einfach nur, damit der Code unter die Leute gemischt wird :) Folgende Demos ist aktuell vorbereitet (oder geplant): * MCP2221 ** ADC/(DAC) ** TI INA219 - Current Shunt & Power Monitor ** (TI INA3221 - 3Ch Current Shunt & Power Monitor) ** Microchip MCP4725 - 12-Bit-DAC ** QMC5883L - Magnetometer ** (STM LSM-irgendwas - 6D-Sensor mit Schrittzähler) ** (Atmel/Microchip Maxtouch-Touchcontroller) ** (Avago/Broadcomm APDS-99x0 - Ambient light/Gesten-/Farb-Sensor) * MCP2210 ** Maxim MAX31855 - K-Typ Temperatursensor ** Maxim MAX7219 - LED-Treiber ** Nordic Semi nRF24L01+ - 2,4 GHz Transceiver (+ [https://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/ BLE-Hack], der Logitech-Hack ist aktuell nicht geplant) ** (TI CC1101 - Low-Power Sub-1 GHz RF Transceiver) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Backplate= Im [[3D-Druck-Sammelsurium]] gibt es Backplates zum Selberdrucken =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= [[Datei:mcp22xx_py.zip]] Python3-Lib v0.2, aktuell nur für MCP2221, mit Beispielen [[Datei:Mcp22xx cs.zip]] C#-Lib v0.1, für MCP2221 und MCP2210, aktuell noch ohne Beispiele und teilweise ungetestet [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 04492b7085182efb13479fed0c5c3b4ae2562554 1394 1391 2020-01-27T20:52:17Z Chris 2 Hinweis zur hidapi-Lib unter Python 3.8 wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. * '''Achtung''': Unter Python >= 3.8 gibt es aktuell wohl keine "wunschlos glücklich" hidapi-Lib. Zumindest bei meinen Versuchen wollte das Teil beim Installieren nicht bauen. Workaround: Python 3.7 verwenden. Deshalb: es wird eine Version 2 geben. Das Datenblatt des MCP2221 enthält ein paar Fehler bzw. fehlen Informationen: * Die Berechnung der I²C-Clock ist eher ungenau * Es fehlen wichtige Informationen zu den Zuständen der Statemachines, die Microchip auch auf Rückfrage nicht herausrücken wollte, für die Implementierung aber zwingend erforderlich sind. Hier musste ich mutmaßen * Im Befehl zum Setzen der SRAM-Settings ist der angegebene Wert zum Schreiben der GPIO-Settings (Byte 7) falsch * Das Umstellen der ADC-Referenz muss nach dem Setzen der Pinfunktion erfolgen, da sonst die Referenz auf den Default-Wert gesetzt werden =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =C#-Lib= Um auch aus C# heraus und nicht (wie mit der Lib von Microchip) an ein .NET-Framework gebunden zu sein, habe ich auch eine Bibliothek sowohl für den MCP2221 als auch MCP2210 in nativem C# (ohne externe DLLs oder sonstige Abhängigkeiten) geschrieben. Einige, für den täglichen Bedarf weniger benötigte, Funktionen wurden ausgelassen; die Performance ist zumindest bei I²C ähnlich gut wie die der Python-Lib. Codebeispiele und entsprechende Anwendungen werden folgen, sobald ich Zeit habe, sie zu vervollständigen. Der unvollständige "Release" ist einfach nur, damit der Code unter die Leute gemischt wird :) Folgende Demos ist aktuell vorbereitet (oder geplant): * MCP2221 ** ADC/(DAC) ** TI INA219 - Current Shunt & Power Monitor ** (TI INA3221 - 3Ch Current Shunt & Power Monitor) ** Microchip MCP4725 - 12-Bit-DAC ** QMC5883L - Magnetometer ** (STM LSM-irgendwas - 6D-Sensor mit Schrittzähler) ** (Atmel/Microchip Maxtouch-Touchcontroller) ** (Avago/Broadcomm APDS-99x0 - Ambient light/Gesten-/Farb-Sensor) * MCP2210 ** Maxim MAX31855 - K-Typ Temperatursensor ** Maxim MAX7219 - LED-Treiber ** Nordic Semi nRF24L01+ - 2,4 GHz Transceiver (+ [https://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/ BLE-Hack], der Logitech-Hack ist aktuell nicht geplant) ** (TI CC1101 - Low-Power Sub-1 GHz RF Transceiver) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Backplate= Im [[3D-Druck-Sammelsurium]] gibt es Backplates zum Selberdrucken =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= [[Datei:mcp22xx_py.zip]] Python3-Lib v0.2, aktuell nur für MCP2221, mit Beispielen [[Datei:Mcp22xx cs.zip]] C#-Lib v0.1, für MCP2221 und MCP2210, aktuell noch ohne Beispiele und teilweise ungetestet [[Datei:MCP-USB-Bridge.zip]] enthält: * Designdaten im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 4b3d607eb0214f53165cbb43350ebe24028dbcd0 Datei:Resol nano 0.1 ts brd.png 6 589 1356 2019-11-10T15:42:19Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol nano 0.1 ts sch.png 6 590 1357 2019-11-10T15:42:42Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:VBus-Python.zip 6 591 1360 2019-11-10T16:27:57Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder/FAQ 0 196 1365 1299 2019-12-10T19:41:37Z Chris 2 /* VBus-Adapter Nano */ wikitext text/x-wiki =Allgemein= *Ich habe eine Solaranlage von der Firma XYZ - kann ich sie mit deiner Schaltung/Software auslesen? Jein. Es kommt darauf an, welche Hardwareschnittstelle und welches Protokoll die Anlage verwendet. Steht Resol drauf, ist die Wahrscheinlichkeit hoch. Auch scheinen (neben meinem Regler) ein paar andere Regler von Viessman die gleiche Schnittstelle zu haben. Ich habe allerdings keinerlei Informationen, welcher Hersteller welche Schnittstelle welches Protokoll verwendet. Leider ;) =VBus-Adapter Nano= * Ist der Adapter mit allen Resol- bzw. Viessmann-Anlagen kompatibel? Vermutlich nein. Manche Resol-Anlagen verwenden wohl RS-485. Ein Indiz für die Kompatibilität ist die Angabe in der Anleitung, dass die Schnittstelle Strom zur Verfügung stellt. Der hier vorgestellte Adapter funktioniert für die Schnittstellen, die ungefähr 8 V ausgeben. * Kann der Adapter direkt an einem Single-Board-Computer (z. B. Raspberry Pi) verwendet werden? Ja. Bisher wurde die Schaltung mit 3,3 und 5 V auf der Sekundärseite getestet. Für 1,8 V I/O-Spannung kann ich noch keine Aussage machen. * Gibt es Software für Single-Board-Computer oder den PC? Nein, noch nicht. Aber es steht auf der (langen) TODO-Liste. Daniel Wippermann hat auf seinem [https://github.com/danielwippermann/ Github-Account] einige Sourcen, auch von [https://github.com/martinvw/vbusdecode martinvw] gibt es etwas dort. Habe bis jetzt keines von beiden Projekten selbst getestet. * Kann der Adapter direkt am PC betrieben werden? Es kommt darauf an. Sowohl für USB als auch RS-232 (klassischer COM-Port) wird ein Adapter benötigt. Für USB tut es ein USB-UART-Adapter (die man z. B. zum Bespielen von Arduinos kennt, Beispiel FT232), für RS-232 muss ein Pegelwandler (z. B. MAX2232) zwischengeschaltet werden. 107d2acc2eaf93eda691bca4944aec8657c5e182 Datei:SaleaeTools.zip 6 592 1366 2019-12-16T21:22:02Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:SerialPlayer.zip 6 593 1367 2019-12-16T21:22:19Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Softwaretools 0 594 1368 2019-12-16T21:23:09Z Chris 2 Seite erstellt wikitext text/x-wiki Warum sollte man sich mit Dingen abmühen, die der Computer viel besser kann als man selbst? An dieser Stelle gibt es ein paar Tools, die das Leben erleichtern sollen. Alles mehr oder weniger gut und sauber programmiert, ohne durchgehende Wartung und ausdrücklichem Verweis auf den [[Hobbyelektronik.org:Impressum#Haftung_f.C3.BCr_Inhalte|Haftungsausschluss]]. =SerialPlayer= Um [[Pirozeda]] vernünftig zu entwickeln und zu debuggen, muss die Software mit Daten stimuliert werden. Lange habe ich hierfür einen Logic8-Nachbau im Rückwärtsbetrieb (der dafür verwendeten Player muss noch verbessert und veröffentlicht werden) und echte Pirozeda-Hardware (HiL, Hardware in the Loop) verwendet, da diese hierbei gleichzeitig mitgetestet werden konnte. Nachdem sie mittlerweile jedoch stabil zu sein scheint und eher die Backend-Software Ärger macht, musste etwas her, um das Backend mit Daten zu füttern. Da ich nichts fertiges gefunden habe das meine Bedürfnisse erfüllt, habe ich es selbst geschrieben. Das Programm liest die angegebene Tab-getrennte Datei ein, die z. B. folgendem Schema entspricht: <pre> #OPT 9600 7O2 0.0 Das 0.1 ist 0.3 ein\tkleiner 1.0 Test\0 1.5 für 2.0 den 2.5 Serial 2.501 Player </pre> und gibt sie mit den entsprechenden Zeitstempeln und Parametern am ausgewähten seriellem Port aus. Eine Ausgabe der Rückgabe findet aktuell nicht statt - alle empfangenen Daten werden verworfen. Neben der Ausgabe von ASCII-Daten kann das Programm auch Hexadezimal codierte Zeichenfolgen ausgeben und auch die Ausgabe wiederholen (praktisch, wenn man länger testen will oder muss). ==Funktionen== Der komplette Funktionsumfang kann in der eingebauten Hilfefunktion eingesehen werden: <pre> >SerialPlayer.exe -h Replays recorded files to a Serial port SerialPlayer.exe -fn filename [-ff tsv-asc|tsv-hex] [-p port] [-b baudrate] [-c config] [--rc repetitions] [--rp pause] -h, --help Show this help and exit -l, --list List available COM-ports -p, --port=VALUE The serial port you want the data to output (COMx) -b, --baudrate=VALUE Baudrate to be used for communication -c, --config=VALUE Configuration for the communication --fn, --file=VALUE File used for transmission --ff, --fileformat=VALUE The file's format: tsv-asc, tsv-hex (default: tsv-asc) --rc, --repeat-count=VALUE Repetition count of output --rp, --repeat-pause=VALUE Pause between repetitions in ms </pre> ==Änderungen== ===2019-12-16 Version 0.1=== * Erster Release ==Download== [[Datei:SerialPlayer.zip]] Version 0.1, Source, Binaries, Beispieldaten =Saleae Tools= Wer die Logic Analyzer von [https://www.saleae.com Saleae] kennt, wird sie vermutlich sehr zu schätzen wissen. Neben dem Anstarren von High- und Lowpegeln kann man auch Analyzer verwenden, um die Kommunikation mittels einiger Protokolle auseinanderzunehmen. Das kann bei längeren Traces in der Software etwas mühselig sein. Aber keine Sorge, sie lassen sich für die Analyse z. B. mit dem hochwissenschaftlichen Werkzeug Excel exportieren. ==Export== Um sich einiges an Herumgeklicke zu ersparen, lassen sich mit dem Tool ausgewählte oder alle Analyzer exportieren: <pre> SaleaeTools.exe -e * </pre> ==Kompression== Leider gibt es bei den exportierten Dateien ein paar Fallstricke - für User mit u. a. deutscher Landeskonfiguration werden in manchen Tools die Kommata der Timestamps nicht richtig interpretiert und jede Zeile entsprechen einem Byte. Das macht die Sache etwas unhandlich: <pre> Time [s],Packet ID,Address,Data,Read/Write,ACK/NAK 0.000685220000000,0,0x20,0x0C,Write,ACK 0.000740220000000,0,0x20,0x0C,Write,NAK 0.001070220000000,1,0x20,0x19,Read,ACK 0.001125220000000,1,0x20,0x19,Read,NAK 0.001380220000000,2,0x24,0x24,Read,ACK 0.001435220000000,2,0x24,0x24,Read,NAK 0.006565220000000,3,0x24,0x13,Read,ACK 0.006620220000000,3,0x24,0x13,Read,NAK 0.008250220000000,4,0x20,0x10,Write,ACK 0.008305220000000,4,0x20,0x10,Write,NAK </pre> Besser wäre es hier doch, alle Bytes aus einer Übertragung in einer Zeile zu haben: <pre> Start time [s];End time [s];Address;Read/Write;Data;ACK/NAK 0,0006852200000;0,0007402200000;20;Write;0C 0C;AN 0,0010702200000;0,0011252200000;20;Read;19 19;AN 0,0013802200000;0,0014352200000;24;Read;24 24;AN 0,0065652200000;0,0066202200000;24;Read;13 13;AN 0,0082502200000;0,0083052200000;20;Write;10 10;AN </pre> Hier merkt man den Unterschied noch nicht so gravierend, aber wie wäre es mit einem realen Beispiel mit UART: <pre> Time [s],Value,Parity Error,Framing Error 0.560297280000000,0xFF,Error, 0.560387280000000,0xAA,,Error 0.560477280000000,0x05,Error,Error 0.560567280000000,0x21,, 0.560657280000000,0x00,, 0.560747280000000,0x06,, 0.560837280000000,0x11,, 0.560927280000000,0x3E,, 1.560343600000000,0xFF,, 1.560433600000000,0xAA,, 1.560523600000000,0x05,, 1.560613600000000,0x21,, 1.560703600000000,0x00,, 1.560793600000000,0x06,, 1.560883600000000,0x12,, 1.560973600000000,0x3F,, 1.759612240000000,0xFF,, 1.759702240000000,0xAA,, 1.759792240000000,0x06,, 1.759882240000000,0x20,, 1.759972240000000,0x01,, 1.760062240000000,0x00,, 1.760152240000000,0x00,, 1.760242240000000,0x01,, 1.760332240000000,0x29,, 1.870662720000000,0xFF,, 1.870752720000000,0xAA,, 1.870842720000000,0x05,, 1.870932720000000,0x10,, 1.871022720000000,0x00,, 1.871112720000000,0x00,, 1.871202720000000,0x04,, 1.871292720000000,0x1A,, </pre> Mit den Parametern <code>SaleaeTools.exe -p ser -if uart.txt -of uart_c1.txt -ld -sh -st 0.1 -ds " " -csh</code> lässt sich Folgendes zaubern: <pre> sep=; Start time [s];End time [s];Values;Errors 0,5602972800000;0,5609272800000;FF AA 05 21 00 06 11 3E;PFB----- 1,5603436000000;1,5609736000000;FF AA 05 21 00 06 12 3F;-------- 1,7596122400000;1,7603322400000;FF AA 06 20 01 00 00 01 29;--------- 1,8706627200000;1,8712927200000;FF AA 05 10 00 00 04 1A;-------- </pre> Damit lassen z. B. auch Datenstrukturen von higher-level-Protokollen einfacher verfolgen. Neben dem Zusammenfassen der Daten wurde hier noch etwas mehr getan: * Aus dem "echten CSV" wurde eines mit Semikolon gemacht, dadurch können... * ...Dezimalstellen mit Komma dargestellt werden (<code>-ld</code>), was ein hiesiges Excel lieber mag * Damit die Tabellenkalkulation die Trennung sofort richtig erkennt, kann der Header <code>sep=</code> (mit <code>-csh</code>) hinzugefügt werden * Ebenso wurde mit dem Parameter <code>-sh</code> das "0x"-Präfix für Hexadezimal-Zahlen entfernt * Die Daten werden mittels <code>-ds " "</code> durch ein Leerzeichen getrennt ==Kombination== Viele Daten ergeben nur im Kontext mit anderen Sinn, deshalb lassen sie sich mit dem Programm auch kombinieren. Zugegeben: Die Funktion ist ziemlich mit der heißen Nadel gestrickt und sollte mit etwas Vorsicht genossen werden. Komprimiert man die exportierten Daten aus Logic mit den richtigen Parametern, lassen sich aber selbst diese kombinieren. z. B. mit folgendem Befehl: <pre> SaleaeTools.exe -c combined.txt single1.txt single2.txt single3.txt </pre> Erzeugt eine eher unübersichtliche Datei - importiert man diese allerdings in eine Tabellenkalkulation, wird alles etwas übersichtlicher. ==Funktionen== <pre> -h, --help Show this help and exit --el, --exportlist Lists the exportable analyzers -e, --export=VALUE Exports selected (comma separated) or all (*) analyzers from Logic. Scripting socket server must be enabled. --ed, --exportdir Lists the exportable analyzers --si, --saleaeip=VALUE IP of the logic client (default: 127.0.0.1) --sp, --saleaeport=VALUE Port of the logic client (default: 10429) -c, --combine=VALUE Combines multiple analyzer export files. Also works with hex compressed files w/o local decimal -p, --protocol=VALUE Protocol of the analyzer export file (SERial|I2C|SPI) --if, --infile=VALUE Input file --of, --outfile=VALUE Output file (optional) --cs, --colsep=VALUE Column separator for output file (default: ;) --csh, --colsephint Hint column separator in CSV-file --ds, --datasep=VALUE Data separator (default: nothing) --ld, --localdecimal Use local decimal separator for timestamps (default: off) --sh, --striphex Strips hexadecimal prefix "0x" --ca, --convertascii Convert Saleae's way of handling ASCII (control characters, COMMA) --st, --septime=VALUE Separation time in ms where separate packets are detected (Serial only) </pre> ==Änderungen== ===2019-12-16 Version 0.1== * Erster Release ==Download== [[Datei:SaleaeTools.zip]] Version 0.1, Source, Binaries, Beispieldaten [[Kategorie:Software]] [[Kategorie:Kleine Helferlein]] b0bdb35abda95b41fbcd98bcd2b29da7e28161e4 1369 1368 2019-12-16T21:23:30Z Chris 2 /* Saleae Tools */ typo wikitext text/x-wiki Warum sollte man sich mit Dingen abmühen, die der Computer viel besser kann als man selbst? An dieser Stelle gibt es ein paar Tools, die das Leben erleichtern sollen. Alles mehr oder weniger gut und sauber programmiert, ohne durchgehende Wartung und ausdrücklichem Verweis auf den [[Hobbyelektronik.org:Impressum#Haftung_f.C3.BCr_Inhalte|Haftungsausschluss]]. =SerialPlayer= Um [[Pirozeda]] vernünftig zu entwickeln und zu debuggen, muss die Software mit Daten stimuliert werden. Lange habe ich hierfür einen Logic8-Nachbau im Rückwärtsbetrieb (der dafür verwendeten Player muss noch verbessert und veröffentlicht werden) und echte Pirozeda-Hardware (HiL, Hardware in the Loop) verwendet, da diese hierbei gleichzeitig mitgetestet werden konnte. Nachdem sie mittlerweile jedoch stabil zu sein scheint und eher die Backend-Software Ärger macht, musste etwas her, um das Backend mit Daten zu füttern. Da ich nichts fertiges gefunden habe das meine Bedürfnisse erfüllt, habe ich es selbst geschrieben. Das Programm liest die angegebene Tab-getrennte Datei ein, die z. B. folgendem Schema entspricht: <pre> #OPT 9600 7O2 0.0 Das 0.1 ist 0.3 ein\tkleiner 1.0 Test\0 1.5 für 2.0 den 2.5 Serial 2.501 Player </pre> und gibt sie mit den entsprechenden Zeitstempeln und Parametern am ausgewähten seriellem Port aus. Eine Ausgabe der Rückgabe findet aktuell nicht statt - alle empfangenen Daten werden verworfen. Neben der Ausgabe von ASCII-Daten kann das Programm auch Hexadezimal codierte Zeichenfolgen ausgeben und auch die Ausgabe wiederholen (praktisch, wenn man länger testen will oder muss). ==Funktionen== Der komplette Funktionsumfang kann in der eingebauten Hilfefunktion eingesehen werden: <pre> >SerialPlayer.exe -h Replays recorded files to a Serial port SerialPlayer.exe -fn filename [-ff tsv-asc|tsv-hex] [-p port] [-b baudrate] [-c config] [--rc repetitions] [--rp pause] -h, --help Show this help and exit -l, --list List available COM-ports -p, --port=VALUE The serial port you want the data to output (COMx) -b, --baudrate=VALUE Baudrate to be used for communication -c, --config=VALUE Configuration for the communication --fn, --file=VALUE File used for transmission --ff, --fileformat=VALUE The file's format: tsv-asc, tsv-hex (default: tsv-asc) --rc, --repeat-count=VALUE Repetition count of output --rp, --repeat-pause=VALUE Pause between repetitions in ms </pre> ==Änderungen== ===2019-12-16 Version 0.1=== * Erster Release ==Download== [[Datei:SerialPlayer.zip]] Version 0.1, Source, Binaries, Beispieldaten =SaleaeTools= Wer die Logic Analyzer von [https://www.saleae.com Saleae] kennt, wird sie vermutlich sehr zu schätzen wissen. Neben dem Anstarren von High- und Lowpegeln kann man auch Analyzer verwenden, um die Kommunikation mittels einiger Protokolle auseinanderzunehmen. Das kann bei längeren Traces in der Software etwas mühselig sein. Aber keine Sorge, sie lassen sich für die Analyse z. B. mit dem hochwissenschaftlichen Werkzeug Excel exportieren. ==Export== Um sich einiges an Herumgeklicke zu ersparen, lassen sich mit dem Tool ausgewählte oder alle Analyzer exportieren: <pre> SaleaeTools.exe -e * </pre> ==Kompression== Leider gibt es bei den exportierten Dateien ein paar Fallstricke - für User mit u. a. deutscher Landeskonfiguration werden in manchen Tools die Kommata der Timestamps nicht richtig interpretiert und jede Zeile entsprechen einem Byte. Das macht die Sache etwas unhandlich: <pre> Time [s],Packet ID,Address,Data,Read/Write,ACK/NAK 0.000685220000000,0,0x20,0x0C,Write,ACK 0.000740220000000,0,0x20,0x0C,Write,NAK 0.001070220000000,1,0x20,0x19,Read,ACK 0.001125220000000,1,0x20,0x19,Read,NAK 0.001380220000000,2,0x24,0x24,Read,ACK 0.001435220000000,2,0x24,0x24,Read,NAK 0.006565220000000,3,0x24,0x13,Read,ACK 0.006620220000000,3,0x24,0x13,Read,NAK 0.008250220000000,4,0x20,0x10,Write,ACK 0.008305220000000,4,0x20,0x10,Write,NAK </pre> Besser wäre es hier doch, alle Bytes aus einer Übertragung in einer Zeile zu haben: <pre> Start time [s];End time [s];Address;Read/Write;Data;ACK/NAK 0,0006852200000;0,0007402200000;20;Write;0C 0C;AN 0,0010702200000;0,0011252200000;20;Read;19 19;AN 0,0013802200000;0,0014352200000;24;Read;24 24;AN 0,0065652200000;0,0066202200000;24;Read;13 13;AN 0,0082502200000;0,0083052200000;20;Write;10 10;AN </pre> Hier merkt man den Unterschied noch nicht so gravierend, aber wie wäre es mit einem realen Beispiel mit UART: <pre> Time [s],Value,Parity Error,Framing Error 0.560297280000000,0xFF,Error, 0.560387280000000,0xAA,,Error 0.560477280000000,0x05,Error,Error 0.560567280000000,0x21,, 0.560657280000000,0x00,, 0.560747280000000,0x06,, 0.560837280000000,0x11,, 0.560927280000000,0x3E,, 1.560343600000000,0xFF,, 1.560433600000000,0xAA,, 1.560523600000000,0x05,, 1.560613600000000,0x21,, 1.560703600000000,0x00,, 1.560793600000000,0x06,, 1.560883600000000,0x12,, 1.560973600000000,0x3F,, 1.759612240000000,0xFF,, 1.759702240000000,0xAA,, 1.759792240000000,0x06,, 1.759882240000000,0x20,, 1.759972240000000,0x01,, 1.760062240000000,0x00,, 1.760152240000000,0x00,, 1.760242240000000,0x01,, 1.760332240000000,0x29,, 1.870662720000000,0xFF,, 1.870752720000000,0xAA,, 1.870842720000000,0x05,, 1.870932720000000,0x10,, 1.871022720000000,0x00,, 1.871112720000000,0x00,, 1.871202720000000,0x04,, 1.871292720000000,0x1A,, </pre> Mit den Parametern <code>SaleaeTools.exe -p ser -if uart.txt -of uart_c1.txt -ld -sh -st 0.1 -ds " " -csh</code> lässt sich Folgendes zaubern: <pre> sep=; Start time [s];End time [s];Values;Errors 0,5602972800000;0,5609272800000;FF AA 05 21 00 06 11 3E;PFB----- 1,5603436000000;1,5609736000000;FF AA 05 21 00 06 12 3F;-------- 1,7596122400000;1,7603322400000;FF AA 06 20 01 00 00 01 29;--------- 1,8706627200000;1,8712927200000;FF AA 05 10 00 00 04 1A;-------- </pre> Damit lassen z. B. auch Datenstrukturen von higher-level-Protokollen einfacher verfolgen. Neben dem Zusammenfassen der Daten wurde hier noch etwas mehr getan: * Aus dem "echten CSV" wurde eines mit Semikolon gemacht, dadurch können... * ...Dezimalstellen mit Komma dargestellt werden (<code>-ld</code>), was ein hiesiges Excel lieber mag * Damit die Tabellenkalkulation die Trennung sofort richtig erkennt, kann der Header <code>sep=</code> (mit <code>-csh</code>) hinzugefügt werden * Ebenso wurde mit dem Parameter <code>-sh</code> das "0x"-Präfix für Hexadezimal-Zahlen entfernt * Die Daten werden mittels <code>-ds " "</code> durch ein Leerzeichen getrennt ==Kombination== Viele Daten ergeben nur im Kontext mit anderen Sinn, deshalb lassen sie sich mit dem Programm auch kombinieren. Zugegeben: Die Funktion ist ziemlich mit der heißen Nadel gestrickt und sollte mit etwas Vorsicht genossen werden. Komprimiert man die exportierten Daten aus Logic mit den richtigen Parametern, lassen sich aber selbst diese kombinieren. z. B. mit folgendem Befehl: <pre> SaleaeTools.exe -c combined.txt single1.txt single2.txt single3.txt </pre> Erzeugt eine eher unübersichtliche Datei - importiert man diese allerdings in eine Tabellenkalkulation, wird alles etwas übersichtlicher. ==Funktionen== <pre> -h, --help Show this help and exit --el, --exportlist Lists the exportable analyzers -e, --export=VALUE Exports selected (comma separated) or all (*) analyzers from Logic. Scripting socket server must be enabled. --ed, --exportdir Lists the exportable analyzers --si, --saleaeip=VALUE IP of the logic client (default: 127.0.0.1) --sp, --saleaeport=VALUE Port of the logic client (default: 10429) -c, --combine=VALUE Combines multiple analyzer export files. Also works with hex compressed files w/o local decimal -p, --protocol=VALUE Protocol of the analyzer export file (SERial|I2C|SPI) --if, --infile=VALUE Input file --of, --outfile=VALUE Output file (optional) --cs, --colsep=VALUE Column separator for output file (default: ;) --csh, --colsephint Hint column separator in CSV-file --ds, --datasep=VALUE Data separator (default: nothing) --ld, --localdecimal Use local decimal separator for timestamps (default: off) --sh, --striphex Strips hexadecimal prefix "0x" --ca, --convertascii Convert Saleae's way of handling ASCII (control characters, COMMA) --st, --septime=VALUE Separation time in ms where separate packets are detected (Serial only) </pre> ==Änderungen== ===2019-12-16 Version 0.1== * Erster Release ==Download== [[Datei:SaleaeTools.zip]] Version 0.1, Source, Binaries, Beispieldaten [[Kategorie:Software]] [[Kategorie:Kleine Helferlein]] 3ccd95ed57801eaa4287535791c95a4b15e2d402 1372 1369 2019-12-16T21:26:34Z Chris 2 /* =2019-12-16 Version 0.1 */ Typo wikitext text/x-wiki Warum sollte man sich mit Dingen abmühen, die der Computer viel besser kann als man selbst? An dieser Stelle gibt es ein paar Tools, die das Leben erleichtern sollen. Alles mehr oder weniger gut und sauber programmiert, ohne durchgehende Wartung und ausdrücklichem Verweis auf den [[Hobbyelektronik.org:Impressum#Haftung_f.C3.BCr_Inhalte|Haftungsausschluss]]. =SerialPlayer= Um [[Pirozeda]] vernünftig zu entwickeln und zu debuggen, muss die Software mit Daten stimuliert werden. Lange habe ich hierfür einen Logic8-Nachbau im Rückwärtsbetrieb (der dafür verwendeten Player muss noch verbessert und veröffentlicht werden) und echte Pirozeda-Hardware (HiL, Hardware in the Loop) verwendet, da diese hierbei gleichzeitig mitgetestet werden konnte. Nachdem sie mittlerweile jedoch stabil zu sein scheint und eher die Backend-Software Ärger macht, musste etwas her, um das Backend mit Daten zu füttern. Da ich nichts fertiges gefunden habe das meine Bedürfnisse erfüllt, habe ich es selbst geschrieben. Das Programm liest die angegebene Tab-getrennte Datei ein, die z. B. folgendem Schema entspricht: <pre> #OPT 9600 7O2 0.0 Das 0.1 ist 0.3 ein\tkleiner 1.0 Test\0 1.5 für 2.0 den 2.5 Serial 2.501 Player </pre> und gibt sie mit den entsprechenden Zeitstempeln und Parametern am ausgewähten seriellem Port aus. Eine Ausgabe der Rückgabe findet aktuell nicht statt - alle empfangenen Daten werden verworfen. Neben der Ausgabe von ASCII-Daten kann das Programm auch Hexadezimal codierte Zeichenfolgen ausgeben und auch die Ausgabe wiederholen (praktisch, wenn man länger testen will oder muss). ==Funktionen== Der komplette Funktionsumfang kann in der eingebauten Hilfefunktion eingesehen werden: <pre> >SerialPlayer.exe -h Replays recorded files to a Serial port SerialPlayer.exe -fn filename [-ff tsv-asc|tsv-hex] [-p port] [-b baudrate] [-c config] [--rc repetitions] [--rp pause] -h, --help Show this help and exit -l, --list List available COM-ports -p, --port=VALUE The serial port you want the data to output (COMx) -b, --baudrate=VALUE Baudrate to be used for communication -c, --config=VALUE Configuration for the communication --fn, --file=VALUE File used for transmission --ff, --fileformat=VALUE The file's format: tsv-asc, tsv-hex (default: tsv-asc) --rc, --repeat-count=VALUE Repetition count of output --rp, --repeat-pause=VALUE Pause between repetitions in ms </pre> ==Änderungen== ===2019-12-16 Version 0.1=== * Erster Release ==Download== [[Datei:SerialPlayer.zip]] Version 0.1, Source, Binaries, Beispieldaten =SaleaeTools= Wer die Logic Analyzer von [https://www.saleae.com Saleae] kennt, wird sie vermutlich sehr zu schätzen wissen. Neben dem Anstarren von High- und Lowpegeln kann man auch Analyzer verwenden, um die Kommunikation mittels einiger Protokolle auseinanderzunehmen. Das kann bei längeren Traces in der Software etwas mühselig sein. Aber keine Sorge, sie lassen sich für die Analyse z. B. mit dem hochwissenschaftlichen Werkzeug Excel exportieren. ==Export== Um sich einiges an Herumgeklicke zu ersparen, lassen sich mit dem Tool ausgewählte oder alle Analyzer exportieren: <pre> SaleaeTools.exe -e * </pre> ==Kompression== Leider gibt es bei den exportierten Dateien ein paar Fallstricke - für User mit u. a. deutscher Landeskonfiguration werden in manchen Tools die Kommata der Timestamps nicht richtig interpretiert und jede Zeile entsprechen einem Byte. Das macht die Sache etwas unhandlich: <pre> Time [s],Packet ID,Address,Data,Read/Write,ACK/NAK 0.000685220000000,0,0x20,0x0C,Write,ACK 0.000740220000000,0,0x20,0x0C,Write,NAK 0.001070220000000,1,0x20,0x19,Read,ACK 0.001125220000000,1,0x20,0x19,Read,NAK 0.001380220000000,2,0x24,0x24,Read,ACK 0.001435220000000,2,0x24,0x24,Read,NAK 0.006565220000000,3,0x24,0x13,Read,ACK 0.006620220000000,3,0x24,0x13,Read,NAK 0.008250220000000,4,0x20,0x10,Write,ACK 0.008305220000000,4,0x20,0x10,Write,NAK </pre> Besser wäre es hier doch, alle Bytes aus einer Übertragung in einer Zeile zu haben: <pre> Start time [s];End time [s];Address;Read/Write;Data;ACK/NAK 0,0006852200000;0,0007402200000;20;Write;0C 0C;AN 0,0010702200000;0,0011252200000;20;Read;19 19;AN 0,0013802200000;0,0014352200000;24;Read;24 24;AN 0,0065652200000;0,0066202200000;24;Read;13 13;AN 0,0082502200000;0,0083052200000;20;Write;10 10;AN </pre> Hier merkt man den Unterschied noch nicht so gravierend, aber wie wäre es mit einem realen Beispiel mit UART: <pre> Time [s],Value,Parity Error,Framing Error 0.560297280000000,0xFF,Error, 0.560387280000000,0xAA,,Error 0.560477280000000,0x05,Error,Error 0.560567280000000,0x21,, 0.560657280000000,0x00,, 0.560747280000000,0x06,, 0.560837280000000,0x11,, 0.560927280000000,0x3E,, 1.560343600000000,0xFF,, 1.560433600000000,0xAA,, 1.560523600000000,0x05,, 1.560613600000000,0x21,, 1.560703600000000,0x00,, 1.560793600000000,0x06,, 1.560883600000000,0x12,, 1.560973600000000,0x3F,, 1.759612240000000,0xFF,, 1.759702240000000,0xAA,, 1.759792240000000,0x06,, 1.759882240000000,0x20,, 1.759972240000000,0x01,, 1.760062240000000,0x00,, 1.760152240000000,0x00,, 1.760242240000000,0x01,, 1.760332240000000,0x29,, 1.870662720000000,0xFF,, 1.870752720000000,0xAA,, 1.870842720000000,0x05,, 1.870932720000000,0x10,, 1.871022720000000,0x00,, 1.871112720000000,0x00,, 1.871202720000000,0x04,, 1.871292720000000,0x1A,, </pre> Mit den Parametern <code>SaleaeTools.exe -p ser -if uart.txt -of uart_c1.txt -ld -sh -st 0.1 -ds " " -csh</code> lässt sich Folgendes zaubern: <pre> sep=; Start time [s];End time [s];Values;Errors 0,5602972800000;0,5609272800000;FF AA 05 21 00 06 11 3E;PFB----- 1,5603436000000;1,5609736000000;FF AA 05 21 00 06 12 3F;-------- 1,7596122400000;1,7603322400000;FF AA 06 20 01 00 00 01 29;--------- 1,8706627200000;1,8712927200000;FF AA 05 10 00 00 04 1A;-------- </pre> Damit lassen z. B. auch Datenstrukturen von higher-level-Protokollen einfacher verfolgen. Neben dem Zusammenfassen der Daten wurde hier noch etwas mehr getan: * Aus dem "echten CSV" wurde eines mit Semikolon gemacht, dadurch können... * ...Dezimalstellen mit Komma dargestellt werden (<code>-ld</code>), was ein hiesiges Excel lieber mag * Damit die Tabellenkalkulation die Trennung sofort richtig erkennt, kann der Header <code>sep=</code> (mit <code>-csh</code>) hinzugefügt werden * Ebenso wurde mit dem Parameter <code>-sh</code> das "0x"-Präfix für Hexadezimal-Zahlen entfernt * Die Daten werden mittels <code>-ds " "</code> durch ein Leerzeichen getrennt ==Kombination== Viele Daten ergeben nur im Kontext mit anderen Sinn, deshalb lassen sie sich mit dem Programm auch kombinieren. Zugegeben: Die Funktion ist ziemlich mit der heißen Nadel gestrickt und sollte mit etwas Vorsicht genossen werden. Komprimiert man die exportierten Daten aus Logic mit den richtigen Parametern, lassen sich aber selbst diese kombinieren. z. B. mit folgendem Befehl: <pre> SaleaeTools.exe -c combined.txt single1.txt single2.txt single3.txt </pre> Erzeugt eine eher unübersichtliche Datei - importiert man diese allerdings in eine Tabellenkalkulation, wird alles etwas übersichtlicher. ==Funktionen== <pre> -h, --help Show this help and exit --el, --exportlist Lists the exportable analyzers -e, --export=VALUE Exports selected (comma separated) or all (*) analyzers from Logic. Scripting socket server must be enabled. --ed, --exportdir Lists the exportable analyzers --si, --saleaeip=VALUE IP of the logic client (default: 127.0.0.1) --sp, --saleaeport=VALUE Port of the logic client (default: 10429) -c, --combine=VALUE Combines multiple analyzer export files. Also works with hex compressed files w/o local decimal -p, --protocol=VALUE Protocol of the analyzer export file (SERial|I2C|SPI) --if, --infile=VALUE Input file --of, --outfile=VALUE Output file (optional) --cs, --colsep=VALUE Column separator for output file (default: ;) --csh, --colsephint Hint column separator in CSV-file --ds, --datasep=VALUE Data separator (default: nothing) --ld, --localdecimal Use local decimal separator for timestamps (default: off) --sh, --striphex Strips hexadecimal prefix "0x" --ca, --convertascii Convert Saleae's way of handling ASCII (control characters, COMMA) --st, --septime=VALUE Separation time in ms where separate packets are detected (Serial only) </pre> ==Änderungen== ===2019-12-16 Version 0.1=== * Erster Release ==Download== [[Datei:SaleaeTools.zip]] Version 0.1, Source, Binaries, Beispieldaten [[Kategorie:Software]] [[Kategorie:Kleine Helferlein]] d200b3d264eba484e787dd4feeee3359b638f345 Datei:Rpizero spacer flat.jpg 6 595 1373 2019-12-25T19:20:35Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Rpizero spacer lifted.jpg 6 596 1374 2019-12-25T19:20:50Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Rpizero spacers.jpg 6 597 1375 2019-12-25T19:20:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 3D-Druck-Sammelsurium 0 598 1376 2019-12-25T19:21:31Z Chris 2 Die Seite wurde neu angelegt: „=Raspberry Pi Zero Spacer= HATs halten auf dem Raspberry Pi zwar über die Stiftleiste schon relativ gut, allerdings ist es doch eine etwas wackelige Angelegen…“ wikitext text/x-wiki =Raspberry Pi Zero Spacer= HATs halten auf dem Raspberry Pi zwar über die Stiftleiste schon relativ gut, allerdings ist es doch eine etwas wackelige Angelegenheit. Mit den Buchsen- und Stiftleisten, die ich verwende (die ebenfalls denen von Reichelt entsprechen dürften), ist der Abstand zwischen den Leiterkarten 11 mm. Solche hat Reichelt aktuell leider nicht im Programm. Warum also nicht selber machen? Einfach nur Distanzbolzen zu drucken ist natürlich langweilig - zudem rollen sie schnell vom Tisch und das anbringen ist eher fummelig. Ein Steg wirkt da Wunder. Am schnellsten (und ohne Materialverschwendung) funktioniert das, wenn er direkt auf der Grundplatte aufliegt. Allerdings ist er dann bei einigen HATs im Weg, daher gibt es zwei Versionen, einmal aufliegend und einmal mit 2 mm Abstand zur Unterseite: <gallery> rpizero_spacers.jpg|Beide Versionen des Abstandshalters rpizero_spacer_flat.jpg|Verbauter flacher Abstandshalter rpizero_spacer_lifted.jpg|Verbauter angehobener Abstandshalter </gallery> ==Download== * [[rpizero_spacer.zip|Download]] Design aus Sketchup Make 2017 & STL-Dateien [[Kategorie:3D-Druck]] [[Kategorie:Raspberry Pi]] [[Kategorie:Pirozeda]] 9cdec26ce1be487b4e45639f681d1272f640471b 1378 1376 2019-12-25T19:24:48Z Chris 2 Download-Link korrigiert wikitext text/x-wiki =Raspberry Pi Zero Spacer= HATs halten auf dem Raspberry Pi zwar über die Stiftleiste schon relativ gut, allerdings ist es doch eine etwas wackelige Angelegenheit. Mit den Buchsen- und Stiftleisten, die ich verwende (die ebenfalls denen von Reichelt entsprechen dürften), ist der Abstand zwischen den Leiterkarten 11 mm. Solche hat Reichelt aktuell leider nicht im Programm. Warum also nicht selber machen? Einfach nur Distanzbolzen zu drucken ist natürlich langweilig - zudem rollen sie schnell vom Tisch und das anbringen ist eher fummelig. Ein Steg wirkt da Wunder. Am schnellsten (und ohne Materialverschwendung) funktioniert das, wenn er direkt auf der Grundplatte aufliegt. Allerdings ist er dann bei einigen HATs im Weg, daher gibt es zwei Versionen, einmal aufliegend und einmal mit 2 mm Abstand zur Unterseite: <gallery> rpizero_spacers.jpg|Beide Versionen des Abstandshalters rpizero_spacer_flat.jpg|Verbauter flacher Abstandshalter rpizero_spacer_lifted.jpg|Verbauter angehobener Abstandshalter </gallery> ==Download== * [[Datei:rpizero_spacer.zip|Download]] Design aus Sketchup Make 2017 & STL-Dateien [[Kategorie:3D-Druck]] [[Kategorie:Raspberry Pi]] [[Kategorie:Pirozeda]] e1c7435be2a33363f3b984ced189bd4b87d1b09c 1381 1378 2019-12-25T22:15:07Z Chris 2 /* Raspberry Pi Zero Spacer */ Schrauben wikitext text/x-wiki =Raspberry Pi Zero Spacer= HATs halten auf dem Raspberry Pi zwar über die Stiftleiste schon relativ gut, allerdings ist es doch eine etwas wackelige Angelegenheit. Mit den Buchsen- und Stiftleisten, die ich verwende (die ebenfalls denen von Reichelt entsprechen dürften), ist der Abstand zwischen den Leiterkarten 11 mm. Solche hat Reichelt aktuell leider nicht im Programm. Warum also nicht selber machen? Einfach nur Distanzbolzen zu drucken ist natürlich langweilig - zudem rollen sie schnell vom Tisch und das anbringen ist eher fummelig. Ein Steg wirkt da Wunder. Am schnellsten (und ohne Materialverschwendung) funktioniert das, wenn er direkt auf der Grundplatte aufliegt. Allerdings ist er dann bei einigen HATs im Weg, daher gibt es zwei Versionen, einmal aufliegend und einmal mit 2 mm Abstand zur Unterseite: <gallery> rpizero_spacers.jpg|Beide Versionen des Abstandshalters rpizero_spacer_flat.jpg|Verbauter flacher Abstandshalter rpizero_spacer_lifted.jpg|Verbauter angehobener Abstandshalter </gallery> Als Schrauben dürften sich am besten M2,5x16 eignen. ==Download== * [[Datei:rpizero_spacer.zip|Download]] Design aus Sketchup Make 2017 & STL-Dateien [[Kategorie:3D-Druck]] [[Kategorie:Raspberry Pi]] [[Kategorie:Pirozeda]] 1649928306ede57535d1dc46e6b9f29413d4b012 1386 1381 2020-01-13T18:41:01Z Chris 2 Neue Backplates wikitext text/x-wiki =Raspberry Pi Zero Spacer= HATs halten auf dem Raspberry Pi zwar über die Stiftleiste schon relativ gut, allerdings ist es doch eine etwas wackelige Angelegenheit. Mit den Buchsen- und Stiftleisten, die ich verwende (die ebenfalls denen von Reichelt entsprechen dürften), ist der Abstand zwischen den Leiterkarten 11 mm. Solche hat Reichelt aktuell leider nicht im Programm. Warum also nicht selber machen? Einfach nur Distanzbolzen zu drucken ist natürlich langweilig - zudem rollen sie schnell vom Tisch und das anbringen ist eher fummelig. Ein Steg wirkt da Wunder. Am schnellsten (und ohne Materialverschwendung) funktioniert das, wenn er direkt auf der Grundplatte aufliegt. Allerdings ist er dann bei einigen HATs im Weg, daher gibt es zwei Versionen, einmal aufliegend und einmal mit 2 mm Abstand zur Unterseite: <gallery> rpizero_spacers.jpg|Beide Versionen des Abstandshalters rpizero_spacer_flat.jpg|Verbauter flacher Abstandshalter rpizero_spacer_lifted.jpg|Verbauter angehobener Abstandshalter </gallery> Als Schrauben dürften sich am besten M2,5x16 eignen. ==Download== * [[Datei:rpizero_spacer.zip|Download]] Design aus Sketchup Make 2017 & STL-Dateien =Diamex AVR-Prog Bodenplatte= Der AVR-Prog ist funktional ein echt schönes Stück Hardware, kommt aber leider komplett ohne Gehäuse. Hat man wie ich einen eher unordentlichen Schreibtisch, ist die Gefahr durch Kurzschlüsse verdammt groß. Deshalb habe ich eine kleine Bodenplatte erstellt, die man auch mit einer M2x6 Senkkopfschraube (bitte nur mit Kunststoffmutter) fixieren kann. <gallery> Backplate_diamex_avr-prog.jpg|AVR-Prog mit angeschnappter Bodenplatte (und gebrochenem Haken) </gallery> Achtung: Die Toleranzen sind sehr eng gewählt, Nacharbeiten können nötig sein. ==Download== * [[Datei:backplate_all-avr.zip|Download]] Design aus Sketchup Make 2017 & STL-Datei =USB-I²C-Bridge Bodenplatte= Ein bisschen mehr Schutz gibt es auch für die [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge|USB-I²C-Bridge]] <gallery> Backplate_mcp_usb_i2c.jpg|Sieht auch transparent schick aus </gallery> Zum Anbringen einfach auf der Seite mit den beiden Schnapphaken einfädeln, die andere Seite mit einem Schraubendreher bisschen aufbiegen und die Leiterkarte eindrücken. Achtung: Die Toleranzen sind sehr eng gewählt, Nacharbeiten können nötig sein. ==Download== * [[Datei:backplate_mcp_i2c_v1.zip|Download]] Design aus FreeCAD 0.18 (nicht voll parametrisch!) & STL-Datei [[Kategorie:3D-Druck]] [[Kategorie:Raspberry Pi]] [[Kategorie:Pirozeda]] 4897494ea9267a376928c9b90543c74571bc2ec4 Datei:Rpizero spacer.zip 6 599 1377 2019-12-25T19:22:51Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Pirozeda-HAT 0 533 1380 1331 2019-12-25T19:28:01Z Chris 2 wikitext text/x-wiki [[Datei:Pirozeda_hat_rpizerow.jpg|300px|thumb|Pirozeda-HAT mit ADuM-Isolator auf Raspberry Pi Zero W]] Wie bereits im [[Pirozeda|Hauptartikel]] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar Geschmackssache aber in Hinblick auf Platz das Beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== '''Noch nicht aufgebaut und getestet.''' Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist, dass neben der gemeinsamen Masse mit der Solaranlage Backfeed entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Diese Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== '''Aufgebaut und erfolgreich getestet.''' Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_opto_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_opto_assy.png|Bestückungsplan mit Optokoppler pirozeda_hat_0.1_opto.jpg|Aufgebauter HAT - es passt sogar ein MJ-Quarz </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R13, R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== '''Aufgebaut und weitestgehend erfolgreich getestet.''' Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator pirozeda_hat_0.1_adum.jpg|Aufgebauter HAT mit Hotfix </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 1 || R9 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} Bei der Schaltungsentwicklung hat sich leider ein dummer Fehler eingeschlichen. Ich dachte nicht daran, dass der ADuM !RES treiben wird - und das v.a. nach GND. Kann man zwar halbwegs in Software umgehen, ist aber Mist. '''Die einfachste Fehlerbeseitigung ist, R10 einfach nicht zu bestücken.''' Der ADuM1301 ist trotz des fehlenden Features die günstigste Lösung. Der Reset des Mikrocontrollers (und damit das Wechseln in den Bootloader) kann auch per Kommando ausgelöst werden. Wer will, kann jedoch auch einen Hotfix implementieren: Dazu muss das obere Pad von R10 von der Leiterbahn getrennt werden (rot). Auf den Pads von R18 (rechts) und R10 kann nun ein BSS138 verdreht aufgesetzt werden. Das obere Pad muss dabei noch mit Masse verbunden werden (orange). <gallery> Pirozeda_hat_0.1_adum_hotfix.png Pirozeda_hat_0.1_adum_hotfix.jpg </gallery> Achtung: Auch mit diesem Hotfix gibt es einen Fallstrick: Ist die "Raspberry Pi"-Seite Stromlos, geht der Ausgangspin des ADuM auf high, folglich hängt Reset bei low (aktiv). Kann seine Vorteile haben, zum Flashen des Mikrocontrollers aber eher unpraktisch. =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== '''Aufgebaut und erfolgreich getestet.''' Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEProm ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SJ1 || || SJ || |- | 1 || C6 || 100n || C0603 || X7R-G0603 100N |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 2 || R3, R4 || 3k3 || R0603 || RND 0603 1 3,3K |} Aktuell gibt es noch keine weitere Unterstützung hierfür. Es handelt sich also eher um ein Gimmick. Den EEProm kann man sich recht günstig von eBay-Modulen "abernten" - einfach im nächsten Abschnitt weiterlesen. ==Real-Time-Clock== '''Aufgebaut und erfolgreich getestet.''' Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R11, R12 || 0 || R0603 || RND 0603 1 0 |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 2 || R6, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. Der Levelshifter kann nach ersten Testes getrost weggelassen werden. Wem der DS1307 bei Reichelt zu teuer ist, kann sich bei eBay ein Modul mit dem Chip, passendem Quarz (der zufällig dem verwendeten entspricht) und einem ebenfalls passenden EEProm besorgen. Der Batteriehalter passt im aktuellen Design leider nicht. <gallery> EBay-RTC-Module.jpg|RTC-Modul als Bauteilspender </gallery> ==Option: I²C(-OLED) + Taster== '''Noch nicht aufgebaut und getestet.''' Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |} ==Status-LEDs== '''Aufgebaut und erfolgreich getestet.''' Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 3 || R24, R25, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || LED1 || gn || CHIP-LED0603 || |- | 2 || LED2, LED3 || or || CHIP-LED0603 || |} LED1 (mitte) zeigt Aktivität an, LED2 (unten) ist mehr oder weniger die Power-LED. Mehr oder weniger, da sie beim Start der Firmware aktiviert wird (nicht aber im Bootloader). Dadurch kann man sehr schnell erkennen, ob sich die Hardware in einem Bootloop befindet. LED3 (oben) kann vom Raspberry Pi angesteuert werden. Standardmäßig sind in der <code>config.h</code> folgende Zeiten für LED1 eingestellt: * Start der Anwendung: 250 ms * Korrekt empfangene Nachrichten: 10 ms * Fehlerhaft empfangene Nachrichten: 200 ms Damit kann man auf den einen Blick erkennen, ob Daten vernünftig ankommen und verarbeitet werden können. =Aufbau der Hardware= ==Bestücken der Leiterkarte== Die Hardware kann im Prinzip in beliebiger Reihenfolge aufgebaut werden. Trotzdem ist es ratsam, die großen/hohen Bauteile zuletzt aufzulöten. Die Steckkräfte einer 2x20 Buchsenleiste sind vergleichsweise groß. Diese können reduziert werden, indem nicht verwendete Pins aus der Buchsenleiste entfernt werden. Um diese nicht wieder (fragt nicht) zurückstecken zu müssen, hier eine Auflistung der benötigten Pins: 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 15, 17, 20, 25, 27, 28, 30, 34, 37, 39. Oder einfach als Bild: <gallery> Pirozeda_hat_0.1_buchsenleiste_pins.png|benötigte Pins (blau markiert) </gallery> Der Wannenstecker lässt sich am einfachsten auflöten, wenn man die Pads auf einer Seite (egal welche) der Leiterkarte bisschen stärker verzinnt. Dadurch kann man den Konnektor ein wenig verklemmen und vor dem Verlöten besser ausrichten. ==Zuleitung== Als Zuleitung habe ich für die ersten Muster den Artikel LIYY 614 (Steuerleitung 6x0,14mm², ungeschirmt) von Reichelt verwendet. Beim Bestellen habe ich leider mehr auf den Preis als die Schirmung geachtet. In Hinblick darauf, dass der Schirm der Buchse im Regler eh nicht mit Masse verbunden ist, ist es eine ziemliche Fummelarbeit, diese mit dem Massepin zu verbinden. Erkenntnisse über die maximale Leitungslänge gibt es noch nicht. Der Vorteil dieser Leitung ist: die Adern können direkt im Pfostenverbinder verpresst werden: <gallery> Pirozeda_hat_0.1_pfosten.jpg </gallery> Ich habe mich für folgende Farbgebung entschieden, beim Pinmapping selbst gibt es keine Wahl: {| class="wikitable" ! Mini-DIN || Signal || Farbe || Wannenstecker |- | 3 || MISO || grau || 1 |- | 4 || GND || braun || 3 |- | 5 || 3V3 || rosa || 5 |- | 6 || MOSI || grün || 2 |- | 7 || SCK || gelb || 4 |- | 8 || !CS || weiß || 6 |} Beim Mini-DIN-Stecker sollte darauf geachtet werden, die äußere Hülle nicht komplett über den Rest zu stülpen, da die Buchse beim Regler ziemlich weit nach innen versetzt ist: <gallery> Pirozeda_hat_0.1_minidin.jpg </gallery> =Firmware= Grundsätzlich läuft die Firmware des Originaldesign auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel und viele neue Features fehlen: Ab 0.2: * Status-LEDs * Uptime-Counter * Messung der Versorgungsspannung * Anzeigen von Bootinformationen ** Resetgrund ** Anzahl der vorherigen Reboots ** Dauer der vorherigen Uptime ** Fusecheck ** Watchdog-Info ** Aktivierte Nachrichten * Neustart + Wechsel in den Bootloader per Kommando * Statistik über empfangene Nachrichten (optional) * Timestamps (optional, aktuell nicht kompatibel mit der Backend-Software) * Erneutes übertragen der Headerinformationen * Kann die Firmware bei einem "Katzen-Paket" miauen. Einfach nur weil. ==Konfiguration== Einige der Features müssen vor dem Kompilieren aktiviert bzw. eingestellt werden. Die Schalter und Defines hierfür befinden sich in zwei Header-Dateien: <code>config.h</code> * <code>PIROZEDA_KITTY_DEBUG</code>: Anzeigen der "Katzen-Pakete" (Vorgabe: inaktiv) * <code>PIROZEDA_TIMESTAMPS</code>: Anzeigen der Timestamps (Vorgabe: inaktiv) * <code>PIROZEDA_WDT_TIMEOUT</code>: Timeout des Watchdogs (Vorgabe: 4 s) * <code>PIROZEDA_UPTIME</code>: Führen der Uptime, abrufbar über den Befehl (Vorgabe: aktiv) * <code>PIROZEDA_SUPPLY_AVGCNT</code>: Anzahl der Messwerte für die Mittelwertbildung der Systemspannung (Vorgabe: 10, maximal: 32) * <code>PIROZEDA_HEADERCNT</code>: Anzahl der Kopfzeilen-Datensätze, die nach dem Start oder Befehl <code>header</code> angezeigt werden (Vorgabe: 200, maximal: 255) * <code>PIROZEDA_STATUS_LED_BOOT</code>: Leuchtdauer der Status-LED nach dem Start (Vorgabe: 100 -> 250 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXOK</code>: Leuchtdauer der Status-LED bei empfangenem Paket (Vorgabe: 4 -> 10 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXERR</code>: Leuchtdauer der Status-LED bei einem Fehler (Vorgabe: 80 -> 200 ms, maximal: 255) * <code>BOOTLOADER_PASSWORD</code>: "Passwort" zum Wechsel in den Bootloader (Vorgabe: "FwUp", maximal 4 Zeichen, darf keine Teilstrings von Befehlen enthalten) <code>prozeda_cfg.h</code> * <code>PROZEDA_USE_COLUMN_NAMES</code>: Verwenden der Spaltennamen (irrelevant für Pirozeda) * <code>PROZEDA_SUPPORT_DISPLAY</code>: Aktiviert den Empfang von Displaydaten (Vorgabe: aktiv) * <code>PROZEDA_SUPPORT_HEADER</code>: Aktiviert den Empfang von Kopfzeilen-Datensätzen (Vorgabe: aktiv) * <code>PROZEDA_IGNORE_KITTY</code>: Ignorieren von Katzen-Paketen, andernfalls werden Fehler ausgegeben (Vorgabe: aktiv) * <code>PROZEDA_MSG_MAXTICKS</code>: Ticks, nach denen ein Paket als abgeschlossen erkannt wird, sollte nur bei Anpassung der CPU-Frequenz angepasst werden (Vorgabe: 3) ==Befehle== Neu ist ab v0.2, dass Befehle an den Mikrocontroller gesendet werden können. Je nach Konfiguration sind dies: * <code>reset</code>: Neustart * <code>uptime</code>: Anzeige der Laufzeit * <code>bootinfo</code>: Anzeigen der Infos, die auch beim (Neu-)Start angezeigt werden * <code>header</code>: Header werden gemäß <code>PIROZEDA_HEADERCNT</code> erneut ausgegeben * <code>stats</code>: Anzeigen der Statistik über empfangene Nachrichten und Empfangsfehler Alle Befehle sind Case-sensitive. ==Flashen der Firmware== Mit den Möglichkeiten steigt die Komplexität. Dadurch dass der die Hardware für die Verwendung mit und ohne Bootloader ausgelegt ist, gibt es mehrere "Pfade" für das Flashen. Wer auf Nummer sicher gehen will, lädt einfach Bootloader und Firmware auf den Mikrocontroller herunter. Selbst wenn man "nur" die Variante mit unidirektionalem UART hat - die Brücken Versorgung und für den UART zum Mikrocontroller ist schneller gelötet als die Stiftleiste für den ISP-Port. Das Einlöten einer wahnsinnig hohen Stiftleiste kann übrigens umgangen werden, indem eine Stiftleiste in das Programmierkabel gesteckt und im Footprint der Buchse "verkeilt" wird. Wirklich keine Dauerlösung aber im Idealfall muss man es nur einmal machen. ===Über Raspberry Pi=== Zunächst muss, wenn nicht schon geschehen, über <code>sudo raspi-config</code> das SPI-Interface aktiviert (reboot nicht vergessen) und [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer#Installation_der_Compiler AVRDUDE installiert] werden. Den Regler vom HAT trennen, nicht vergessen, dass R10 oder der Hotfix entfernt werden muss, falls der ADuM-Isolator verwendet und einseitig versorgt (also nicht auf dem Raspi steckt) wird und anschließend den SPI-Port mit SV2 verbinden. {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin |- | MISO || 1 || BCM 9 || 21 |- | 3V3 || 2 || 3V3 || 17 |- | SCK || 3 || BCM 11 || 23 |- | MOSI || 4 || BCM 10 || 19 |- | !RES || 5 || BCM 25 || 22 |- | GND || 6 || GND || 20 |} ====Mit Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = FC }} Die empfohlene Variante (auch wenn man nicht beabsichtigt, den Bootloader zu nutzen). Mit Bootloader sind das folgende Befehle: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0xFC:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_fboot_0.2.hex" </source> ====Ohne Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} 'cause I ain't gonna judge you <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_0.2.hex" </source> ==Update der Firmware== In Sachen Bootloader bin ich ein großer Fan von [https://www.mikrocontroller.net/articles/AVR_Bootloader_FastBoot_von_Peter_Dannegger Peter Danneggers Fastboot]. Er ist klein, schnell und zuverlässig. Um einen kleinen Unterschied zu machen, lautet das Passwort zum Starten nicht "Peda" sondern "FwUp", was ein kleines Problem mit sich bringt. "Peda" ist nicht nur der Spitzname vom Autor, das "a" wird zur automatischen Baudratenerkennung verwendet. Das von mir gewählte Passwort hat das nicht zu bieten. Was mir bei der Verwendung von [https://luani.de/projekte/updateloader/ UpdateLoader] aufgefallen ist: es funktioniert trotzdem. Ganz einfach, weil der Autor ein "a" voranstellt. Das funktioniert dann auch mit so gut wie allen anderen Download-Tools. ===Mit Bootloader=== Das Firmware-Update funktioniert nur bei bidirektionaler UART-Kommunikation mit dem Mikrocontroller, also bei der Variante Direkt und ADuM-Isolator. Wenn man mutig ist, kann man bei der Optokoppler-Variante R19 und R27 bestückt werden. In jedem Fall muss die Mikrocontroller-Seite mit Strom versorgt werden, also am einfachsten am Solarregler angeschlossen lassen. Berhard M. (boregard) hat das Programm [https://www.mikrocontroller.net/topic/73196#1067153 lboot] (auch im Download-Paket) geschrieben, das unter Linux mit dem schönen Fastboot von Peter Danegger spricht. Damit der Download funktioniert, muss das Pirozeda-Backend (und andere Software, die auf das UART-Interface zugreift) beendet werden. <source lang="shell"> ./bootloader -d /dev/serial0 -b 115200 -t 1024 -p pirozeda_0.2.hex -P aFwUp </source> ===Ohne Bootloader=== siehe [[#Flashen_der_Firmware]] =Einrichten der Optionen= ==HAT-ID== Wie bereits weiter oben geschrieben, ist der HAT-EEProm momentan eher ein Gimmick als wirklich genutztes Feature. Die Anwendung zur Generierung der Daten kann im [https://github.com/raspberrypi/hats/tree/master/eepromutils GitHub-Repo] vom Raspberry Pi heruntergeladen werden. Da der EEProm im normalen Betrieb schreibgeschützt ist, muss SJ1 gebrückt werden - am besten mit einem guten Klecks Lötzinn. Anschließend kann mit dem Script eepflash.sh (liegt dem Download-Paket bei) das EEProm-Image geschrieben werden: <source lang="bash"> sudo ./eepflash.sh -w -f=pirozeda-hat_id.eep -t=24c32 -a=50 </source> Aktuell sind weder Product-ID noch Version-ID vergeben, ansonsten ist die Konfiguration wie folgt: <pre> # Start of atom #0 of type 0x0001 and length 60 # Vendor info product_uuid 9edc3aef-683c-4007-b2f2-3ea4969b1737 product_id 0x0000 product_ver 0x0000 vendor "hobbyelektronik.org" # length=19 product "Pirozeda HAT v0.1" # length=17 # End of atom. CRC16=0x9a75 # Start of atom #1 of type 0x0002 and length 32 # GPIO map info gpio_drive 0 gpio_slew 0 gpio_hysteresis 0 back_power 0 # GPIO FUNCTION PULL # ---- -------- ---- setgpio 22 INPUT UP setgpio 26 OUTPUT NONE </pre> ==RTC== Die [http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-RTC/index.html Netzmafia] hat einen recht guten Artikel, wie man die hwclock bedient. Wer sich nicht einlesen will, hier im Schnelldurchlauf: Testen der RTC: <source lang="shell"> #call bash as superuser, this is needed to get the echo working properly sudo bash modprobe rtc-ds1307 echo "ds1307 0x68" > /sys/class/i2c-adapter/i2c-1/new_device #Auslesen der Uhr hwclock --debug -r exit </source> Dauerhaftes aktivieren der RTC: <source lang="shell"> sudo bash # enable module echo "# enable DS1307-RTC" >> /etc/modules echo "rtc-ds1307" >> /etc/modules # remove fake-hwclock update-rc.d -f fake-hwclock disable update-rc.d -f fake-hwclock remove apt-get remove fake-hwclock # overwrite prepared configuration of hwclock cp /etc/init.d/hwclock.sh ./hwclock.old cat ./hwclock.new > /etc/init.d/hwclock.sh # enable start/stop script update-rc.d hwclock.sh enable exit </source> Laut Anleitung von Netzmafia muss die Datei <code>/etc/init.d/hwclock.sh</code> noch wie folgt angepasst werden: <source lang="text"> Nun muss noch das Start/Stopp-Script für die RTC angepasst werden. Dazu wird (als root-User) die Datei /etc/init.d/hwclock.sh mit dem Editor bearbeitet. Zunächst tragen Sie am Anfang des Scripts die Default-Wert ein bzw. überprüfen diese: # These defaults are user-overridable in /etc/default/hwclock BADYEAR=no HWCLOCKACCESS=yes HWCLOCKPARS=' --noadjfile --utc' HCTOSYS_DEVICE=rtc0 Nach der Zeile 'case "$1" in start)' werden die folgenden drei Zeilen auskommentieren ('#' davorsetzen): #if [ -d /run/udev ] || [ -d /dev/.udev ]; then # return 0 #fi </source> Um das zu vereinfachen, habe ich eine SH-Datei vorbereitet, natürlich muss sich diese (<code>hwclock.new</code>) im gleichen Verzeichnis liegen, damit es funktioniert. Im Ordner <code>options/rtc</code> befindet sich sowohl die <code>rtc-test.sh</code> als auch <code>rtc-enable.sh</code>. Da diese über meinen Windows-PC gewandert sind und dadurch ihre Dateieigenschaften verloren haben, müssen sie entweder als ausführbar markiert werden oder mit <code>/bin/bash</code> gestartet werden: <source lang="shell"> sudo /bin/bash rtc-test.sh </source> ==I²C + Taster== Für die Verwendung des I²C muss eigentlich nur in <code>raspi-config</code> das I²C-Interface aktiviert werden. Mit der Konfiguration im ID-EEPRom wird der Taster in den Device-Tree eingebunden, allerdings kann er prinzipiell auch ohne angesprochen werden. =Backend= Das Back- und Frontend aus [[Pirozeda]] kann prinzipiell weiterverwendet werden. Es gibt allerdings noch keinen Support der neuen Features. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Mechanik= Im [[3D-Druck-Sammelsurium]] gibt es einen Spacer zwischen Raspberry Pi Zero und dem Hat. =Verbesserungsmöglichkeiten= * Korrektur der Reset-Beschaltung * ESD-Schutz hinzufügen. Aktuell können auf den Footprints von C7, C11 und C14 ESD-Schutzdioden wie B72500D50A60 von Reichelt bestückt werden. Allerdings ist die Positionierung nicht ideal * Stiftwanne für den SPI-Schnittstelle oben auf der Leiterkarte platzieren * Die Widerstände für die Direktverbindung so platzieren, dass sie für das Bootloader-Update einfacher bestückt werden können (oder gleich Jumper) * Hinzufügen der Batteriehalter der billigen RTC-Module (Recycling FTW!) * Entfernen des nicht benötigten I²C-Levelshifters * Vermeiden von Backfeed in der Direkt-Variante =Download= [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format * Quellen des Bootloaders von Peter Dannegger * Quellen der Firmware + flashbare Images * Scripts für die Einrichtung der Optionen [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 61469d277cee9bc72841646281db97a7f193c8f5 Datei:Backplate diamex avr-prog.jpg 6 600 1382 2020-01-13T18:39:40Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Backplate mcp usb i2c.jpg 6 601 1383 2020-01-13T18:39:53Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Backplate mcp i2c v1.zip 6 602 1384 2020-01-13T18:40:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Backplate all-avr.zip 6 603 1385 2020-01-13T18:40:21Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Mcp22xx py.zip 6 515 1389 1199 2020-01-19T20:07:08Z Chris 2 Chris lud eine neue Version von [[Datei:Mcp22xx py.zip]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f 1395 1389 2020-01-27T20:55:36Z Chris 2 Chris lud eine neue Version von [[Datei:Mcp22xx py.zip]] hoch wikitext text/x-wiki Datei hochgeladen mit MsUpload 72024344f3e6b65ca3728cef027140b39fd69f2f Pirozeda 0 487 1392 1338 2020-01-19T20:21:33Z Chris 2 /* 2019-03-30: Version 0.4 */ wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht entweder über <code>sudo raspi-config</code> (keine Konsole aber UART aktiv) oder in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. ===Vor Pirozeda 0.4=== Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ===Ab Pirozeda 0.4=== Pirozeda ab 0.4 verwendet Python 3. Dementsprechend müssen die Module für die neuere Plattform installiert werden. Für JSON-RPC wird nun eine andere Lib verwendet, die zugleich "Werkzeug" als Webserver verwendet: <source lang="shell"> sudo python3 -m pip install json-rpc werkzeug pyserial </source> Auch hier kann über <code>miniterm</code> geprüft werden, ob Daten ankommen. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. ===Vor Pirozeda 0.4=== Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ===Ab Pirozeda 0.4=== Ab Pirozeda 0.4 kann das Script als [http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/ Service] ausgeführt werden. Das entsprechende Script ist für die Verwendung in <code>/home/pi/pirozeda</code> vorbereitet und kann einfach wie folgt installiert werden: <source lang="shell"> sudo chmod +x pirozeda.py sudo cp pirozeda.sh /etc/init.d sudo chmod +x /etc/init.d/pirozeda.sh sudo update-rc.d pirozeda.sh defaults sudo /etc/init.d/pirozeda.sh start </source> Wer Pirozeda woanders installieren möchte, kann das Shellscript jederzeit entsprechend anpassen. Auch die Verwendung von cron ist natürlich weiterhin möglich, allerdings muss nun python3 verwendet werden. Update 21.04.2019: <code>pirozeda.py</code> muss für die Verwendung der Shell-Datei ebenfalls als ausführbar markiert sein. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= ==Vor Pirozeda 0.4== [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Ab Pirozeda 0.4== [[Datei:Pirozeda rpi.zip]] enthält: * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) === 2019-03-30: Version 0.4 === * Umstellung Auf Python 3 * Script kann nun als Service verwendet werden * Fehlerkorrektur Anzeige von Volumenstrom * Mehr Informationen von der Firmware (Version/Build/Reglerversion/...) Ich habe leider keine Vergleichsdaten aber mir scheint die CPU-Last auf dem Pi bei aktivem Frontend sehr hoch, kann das jemand bestätigen? '''Kürzlich kam eine Meldung über Instabilitäten rein, die Fehlersuche ist gestartet, es gibt aber leider noch keine Ergebnisse. Wer möchte, kann sich gerne bei mir für die aktuelle Alpha melden.''' [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 8c45dc272e45df94c07652ad6236ea9d4f06131c Benutzer:Chris 2 45 1396 946 2020-01-29T20:52:58Z Chris 2 /* Was ich mache */ irrelevantes entfernt. wikitext text/x-wiki = Wie es dazu kam = Irgendwann um 2003 fing ich damit an, meine (mehr oder weniger gelungenen) Bastel-Projekte in HTML zu verwandeln und auf hobby-elektronik.de.vu zu veröffentlichen. Der Speicherplatz bei Tripod wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich irgendwann, auf das schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10 April 2005 die Domain hobbyelektronik.org registriert. Zu .org kam es, da mir eine Woche davor jemand die .net-Domain weggeschnappte. Im Nachhinein bin ich glücklich, dem damaligen .net-Hype entgangen zu sein. Eine richtige Organisation sind wir zwar noch immer nicht aber was nicht ist, kann ja noch werden ;) = Was ich mache = Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" bezeichnen. Von Oktober 2009 bis Juli 2013 habe ich Elektrotechnik/Nachrichtentechnik an der [http://www.hs-ulm.de Hochschule Ulm] studiert und Arbeite seit Oktober 2013 im Automotive-Bereich. Die Schnittmenge bzw. vielmehr die Verbindung aus den beiden Bereichen kommen auch wieder in meinen Hobbys zusammen. = Warum das Ganze? = Ganz einfach: Weil es mir Spaß macht. Wie an anderer Stelle schon erwähnt, bezeichne ich diese Seite als "nicht-kommerzielles Umfeld". Damit ist gemeint, dass ich mit dieser Homepage kein Geld verdiene (keine Werbung, keine Partnerschaften mir irgendwelchen Firmen, etc.) und es ehrlich gesagt auch nicht will. Das bedeutet auch, dass Produkterwähnungen und evtl. auch Empfehlungen aus meiner eigenen Erfahrung und Meinung gemacht werden. (Wer spenden will - gerne auch Sachspenden - ist natürlich willkommen ;)). Neben dem Spaß geht es mir auch darum, etwas an andere Bastler, Elektronik-Einsteiger und DICH weiter- bzw. zurückzugeben. Auch ich habe mal sehr klein angefangen und war froh um alles, was mich näher in Richtung Computer und Elektronik brachte (und auch heute noch bringt). Wenn man so will, kann man es als Kreislauf verstehen :) [http://sprut.de/misc/hpphilos.htm Sprut] hat es meiner Meinung mit seiner Homepage-Philosophie sehr gut getroffen. = Kannst du mir... = ...bei <Thema hier einsetzen> helfen? Jein. Wenn du ehrliches Interesse hast, helfe ich gerne. Was ich allerdings überhaupt nicht abkann ist die "Mach mal"- bzw. "Freibiermentalität", die manche an den Tag legen. Solche "Anfragen" lasse ich liegen. = Kontakt = Solltest du Fragen, Kritik, Verbesserungsvorschläge oder Fehler auf den Seiten hier gefunden haben - eine kleine Mail genügt und wird gerne beantwortet: chris at hobbyelektronik punkt org Wer mich in sozialen Netzwerken sucht, wird wenig erfolg haben. Will ich nicht, mach ich nicht. (siehe auch [[Hobbyelektronik.org:Impressum|Impressum]]) 5f5d51d97be409f7f23c44a919bf31735f42d204 Hobbyelektronik.org:Impressum 4 4 1397 1304 2020-01-29T21:57:56Z Chris 2 Ein paar Hinweise zur Kontaktaufnahme und zu Spenden wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung nur eine Konversation in 2-3 Jahren mit verschlüsselten Mails stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. ==Fragen/Hilfe/Unterstützung== Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Es geht um Dinge, die mich interessieren (oder einmal interessierten). Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard- und Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schnell (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzprüfung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Andersrum: es gab noch nicht einmal eine Antwort auf die Mail. Da merkt man, wo deren Herz schlägt. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich "übrige" Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das "schlechte Gewissen" zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet), darf einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine "Win-Win-Win-Situation": Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. Alles Kann, kein Muss. Bei den Leiterkarten möchte ich jedoch doch darauf hinweisen: Die fallen nicht vom Baum, genauso die Aufwendungen für den Versand. Wichtig ist mir nur, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. "Absolut richtig" zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krebshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und "Bettelbriefe" steckt. * Fragwürdig halte ich ebenfalls PeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kirche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Kirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) 8451e76b280aa6717b7f82aa9c3ca79df3acef22 1398 1397 2020-01-29T21:58:23Z Chris 2 /* Fragen/Hilfe/Unterstützung */ Falsche Einrückung, muss an der Tageszeit liegen... wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung nur eine Konversation in 2-3 Jahren mit verschlüsselten Mails stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Es geht um Dinge, die mich interessieren (oder einmal interessierten). Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard- und Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schnell (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzprüfung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Andersrum: es gab noch nicht einmal eine Antwort auf die Mail. Da merkt man, wo deren Herz schlägt. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich "übrige" Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das "schlechte Gewissen" zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet), darf einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine "Win-Win-Win-Situation": Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. Alles Kann, kein Muss. Bei den Leiterkarten möchte ich jedoch doch darauf hinweisen: Die fallen nicht vom Baum, genauso die Aufwendungen für den Versand. Wichtig ist mir nur, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. "Absolut richtig" zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krebshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und "Bettelbriefe" steckt. * Fragwürdig halte ich ebenfalls PeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kirche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Kirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) eaad02b0d1758efbd5bfb9a1a1f70eecdf4c664a 1399 1398 2020-01-29T22:00:35Z Chris 2 Wörter wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung nur eine Konversation in 2-3 Jahren mit verschlüsselten Mails stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Es geht um Dinge, die mich interessieren (oder einmal interessierten). Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schnell (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzprüfung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Andersrum: es gab noch nicht einmal eine Antwort auf die Mail. Da merkt man, wo deren Herz schlägt. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich "übrige" Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das "schlechte Gewissen" zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet), darf einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine "Win-Win-Win-Situation": Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. Alles Kann, kein Muss. Bei den Leiterkarten möchte ich jedoch doch darauf hinweisen: Die fallen nicht vom Baum, genauso die Aufwendungen für den Versand. Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. "Absolut richtig" zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krebshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und "Bettelbriefe" steckt. * Fragwürdig halte ich ebenfalls PeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kirche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Kirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) fb0d8b7466f4fd45731185acbbcfacad025575c3 1432 1399 2020-03-28T17:40:17Z Chris 2 /* Spenden */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung nur eine Konversation in 2-3 Jahren mit verschlüsselten Mails stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Es geht um Dinge, die mich interessieren (oder einmal interessierten). Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schnell (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzprüfung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. '''Nachtrag 15.04.2016: Nachdem in letzter Zeit immer mehr Mails von irgendwelchen Agenturen kommen: Ich möchte diese Angebote ausdrücklich nicht! Jede Person, die diesen Wunsch missachtet, ist aufgefordert, die Hosting-Kosten für einen Monat zu übernehmen.''' =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich "übrige" Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das "schlechte Gewissen" zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet), darf einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine "Win-Win-Win-Situation": Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, genauso die Kosten für den Versand.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. "Absolut richtig" zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krebshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und "Bettelbriefe" steckt. * Fragwürdig halte ich ebenfalls PeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kirche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Kirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) 24cdad9315fe6be13131a9737e17d44d81f2a386 1433 1432 2020-03-28T17:40:35Z Chris 2 /* Werbung */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung nur eine Konversation in 2-3 Jahren mit verschlüsselten Mails stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Es geht um Dinge, die mich interessieren (oder einmal interessierten). Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schnell (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzprüfung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich "übrige" Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das "schlechte Gewissen" zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet), darf einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine "Win-Win-Win-Situation": Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, genauso die Kosten für den Versand.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. "Absolut richtig" zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krebshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und "Bettelbriefe" steckt. * Fragwürdig halte ich ebenfalls PeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kirche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Kirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) 558037e8a6c439cfe09393074435ed47c5e39071 Datei:Vbus pi.zip 6 604 1400 2020-02-15T20:07:10Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.1 assy bot.png 6 605 1401 2020-02-15T20:07:23Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.1 assy sch.png 6 606 1402 2020-02-15T20:07:43Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.1 assy top.png 6 607 1403 2020-02-15T20:07:49Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.0 bare.jpg 6 608 1404 2020-02-15T20:07:54Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 1407 1404 2020-02-15T20:15:32Z Qsysopr 1 Qsysopr verschob die Seite [[Datei:Vbuspi nano 1.0 bare.jpg]] nach [[Datei:Vbuspi 1.0 bare.jpg]], ohne dabei eine Weiterleitung anzulegen wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder 0 120 1405 1364 2020-02-15T20:10:55Z Chris 2 Es gibt wieder Leiterkarten - und einen Adapter für den Raspi wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Troubleshooting== Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. ==Leiterkarten== Es gibt wieder Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =Vbus-Adapter für den Raspberry Pi= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 assy bare.jpg|Unbestückte Leiterkarte (v1.0) </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. ==Fehler & Verbesserungen== Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht ==Leiterkarten== Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. ==Weiteres== Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Python-Implementierung= Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie und Gewährleistung: * [[Datei:VBus-Python.zip]] =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano *[[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 9ac70bbd7a1b9c007b9a3952963e4581ea23984b 1406 1405 2020-02-15T20:12:45Z Chris 2 /* Vbus-Adapter für den Raspberry Pi */ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Troubleshooting== Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. ==Leiterkarten== Es gibt wieder Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =Vbus-Adapter für den Raspberry Pi= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. ==Fehler & Verbesserungen== Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht ==Leiterkarten== Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. ==Weiteres== Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Python-Implementierung= Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie und Gewährleistung: * [[Datei:VBus-Python.zip]] =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano *[[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 99e5480aadc66051b5e5f6433c386e5fcdf89129 1408 1406 2020-02-15T20:16:40Z Qsysopr 1 /* Vbus-Adapter für den Raspberry Pi */ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Troubleshooting== Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. ==Leiterkarten== Es gibt wieder Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =VBus-Adapter für den Raspberry Pi= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. ==Fehler & Verbesserungen== Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht ==Leiterkarten== Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. ==Weiteres== Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Python-Implementierung= Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie und Gewährleistung: * [[Datei:VBus-Python.zip]] =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano *[[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 8332bc1e2a8a85b0d4ef5bd7ffd50ab6cc5fd041 Pirozeda-HAT 0 533 1409 1380 2020-02-15T20:22:59Z Qsysopr 1 /* Verbesserungsmöglichkeiten */ wikitext text/x-wiki [[Datei:Pirozeda_hat_rpizerow.jpg|300px|thumb|Pirozeda-HAT mit ADuM-Isolator auf Raspberry Pi Zero W]] Wie bereits im [[Pirozeda|Hauptartikel]] und im Blog erwähnt, sind bei der ersten Leiterkarte ein paar Dinge unschön. Deshalb habe ich mich noch einmal hingesetzt und ein Design mit anderen Kompromissen erstellt: * Entspricht (größtenteils) den Raspberry Pi HAT-Spezifikationen (inkl. EEProm) * Neben dem Optokoppler kann man nun auch einen ADUM1301 verwenden * ...oder einfach Widerstände, wenn man sich der Sache sicher ist * Mit ADUM1301 oder Direktverbindung können nun hardwareseitig einfach Firmware-Updates aufgespielt und der µC resettet werden * Am Mikrocontroller gibt es nun die Option für zwei, vom Raspi für eine Status-LED * Es gibt nun eine RTC (DS1307Z), um direkt nach einem Neustart oder bei fehlendem Netzwerk loggen zu können * Der I2C des Raspberry ist auf eine Stiftleiste herausgeführt, ideal für eines dieser kleinen OLED-Displays. * Ein GPIO des Raspberry ist auf einen Taster herausgeführt Ein großer Kompromiss ist, dass das Layout (wieder) nicht so richtig für den Raspberry Pi B passt. Die Buchse für den Bus kann bei "normalem" Boardabstand (in der Höhe) nicht bestückt werden. Zwar kann ein Flachbandkabel direkt an die Kontaktflächen gelötet werden, so richtig schön ist das allerdings auch nicht. Ich habe die verschiedenen Platzierungsmöglichkeiten durchprobiert aber mit dem Featureset ist es mir nicht gelungen, die Buchse an eine andere Stelle zu packen. Die Mini-DIN-Buchse ist übrigens rausgeflogen, weil sie - neben dem großen Platzbedarf - keinen wirklichen Mehrwert hat. Konfektionierte Kabel konnte ich bis jetzt nicht finden und selber bauen ist eher fummelig. Da reicht es schon, einen Mini-DIN-Stecker zu löten. die Stiftwanne seitlich an die Leiterkarte zu Löten ist zwar Geschmackssache aber in Hinblick auf Platz das Beste, was mir eingefallen ist. Es steht natürlich jedem frei, das Design zu verbessern. =Bestückungsvarianten= Durch die verschiedenen Möglichkeiten für das Interface gibt es einige Bestückungsoptionen. Drei für das eigentliche Interface und je nachdem, wie viele Zusatzfeatures aktiviert werden sollen, noch ein paar mehr: ==Variante 1: Direkt== '''Noch nicht aufgebaut und getestet.''' Mit der Bestückungsvariante "direkt" kann ich nur abraten, habe sie aber der Vollständigkeit halber erstellt. Problem an ihr ist, dass neben der gemeinsamen Masse mit der Solaranlage Backfeed entstehen kann, wenn der Raspberry Pi keine Stromversorgung hat. Der Strom wird zwar über Widerstände begrenzt, Fehlfunktion kann aber nicht ausgeschlossen werden. Diese Variante ist eher für diejenigen, die sich der Sache sicher sind. Einen Vorteil gibt es natürlich auch: es ist die günstigste Variante und wenn ein UART-Bootloader geflasht wurde lässt sich der AVR darüber updaten. <gallery> pirozeda_hat_0.1_direct_sch.png|Schaltplan mit Direktverbindung pirozeda_hat_0.1_direct_assy.png|Bestückungsplan mit Direktverbindung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 3 || R22, R26, R27 || 0 || R0805 || RND 0805 1 0 |- | 3 || R18, R19, R20 || 100 || R0805 || RND 0805 1 100 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 2: Optokoppler== '''Aufgebaut und erfolgreich getestet.''' Dies entspricht weitestgehend dem Originaldesign. Heißt: optische Isolation, Firmware-Updates gehen nur über SPI oder drei bzw. 4 Jumper (R18, R19, R27 und ggf. R22). <gallery> pirozeda_hat_0.1_opto_sch.png|Schaltplan mit Optokoppler pirozeda_hat_0.1_opto_assy.png|Bestückungsplan mit Optokoppler pirozeda_hat_0.1_opto.jpg|Aufgebauter HAT - es passt sogar ein MJ-Quarz </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 4 || R13, R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} ==Variante 3: ADUM-Isolator== '''Aufgebaut und weitestgehend erfolgreich getestet.''' Die "zukunftssichere" aber gleichzeitig auch die teuerste Variante. Unterstützt Bootloader und gewährleistet die Isolation zwischen Solaranlage und Raspberry Pi. <gallery> pirozeda_hat_0.1_adum_sch.png|Schaltplan mit ADUM-Isolator pirozeda_hat_0.1_adum_assy.png|Bestückungsplan mit ADUM-Isolator pirozeda_hat_0.1_adum.jpg|Aufgebauter HAT mit Hotfix </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 1 || SV1 || || ML6S || WSL 6G |- | 1 || R21 || 0 || R0805 || RND 0805 1 0 |- | 1 || R9 || 100 || R0603 || RND 0603 1 100 |- | 4 || C1, C5, C9, C10 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || X7R-G0603 10p |- | 1 || Q2 || 12M || HC49UP || 12,0000-HC49-SMD |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || IC4 || ADUM1301ARW || SO-16W || ADUM 1301 ARW |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || CL1 || Datacable || DUMMY || LIYY 614-5,0 |- | 1 || SV5 || IDC-Conn 6 0.1in || DUMMY || PFL 6 |- | 1 || IC3 || MEGA48/88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || SV4 || Mini-DIN 8 plug || DUMMY || SE-DIO M08 |- | 1 || X1 || RPI_CONDENSEDZERO || RPI_ZERO_THT || BL 2X25G8 2,54 |} Bei der Schaltungsentwicklung hat sich leider ein dummer Fehler eingeschlichen. Ich dachte nicht daran, dass der ADuM !RES treiben wird - und das v.a. nach GND. Kann man zwar halbwegs in Software umgehen, ist aber Mist. '''Die einfachste Fehlerbeseitigung ist, R10 einfach nicht zu bestücken.''' Der ADuM1301 ist trotz des fehlenden Features die günstigste Lösung. Der Reset des Mikrocontrollers (und damit das Wechseln in den Bootloader) kann auch per Kommando ausgelöst werden. Wer will, kann jedoch auch einen Hotfix implementieren: Dazu muss das obere Pad von R10 von der Leiterbahn getrennt werden (rot). Auf den Pads von R18 (rechts) und R10 kann nun ein BSS138 verdreht aufgesetzt werden. Das obere Pad muss dabei noch mit Masse verbunden werden (orange). <gallery> Pirozeda_hat_0.1_adum_hotfix.png Pirozeda_hat_0.1_adum_hotfix.jpg </gallery> Achtung: Auch mit diesem Hotfix gibt es einen Fallstrick: Ist die "Raspberry Pi"-Seite Stromlos, geht der Ausgangspin des ADuM auf high, folglich hängt Reset bei low (aktiv). Kann seine Vorteile haben, zum Flashen des Mikrocontrollers aber eher unpraktisch. =Bestückungsoptionen= Da nicht jeder alle Funktionen braucht, hier noch die zusätzlichen Bestückungsoptionen: <gallery> pirozeda_hat_0.1_assy_optional.png|Zusätzliche Bestückungsoptionen </gallery> * HAT-ID (violett) * Real-Time-Clock (orange) * I²C(-OLED) (grün) * Taster (cyan) * Status-LEDs (blau) ==HAT-ID== '''Aufgebaut und erfolgreich getestet.''' Die [https://github.com/raspberrypi/hats Raspberry Pi HAT Specification] schließt einen I²C-EEProm ein. Dieser kann bei Bedarf bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SJ1 || || SJ || |- | 1 || C6 || 100n || C0603 || X7R-G0603 100N |- | 1 || R2 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || IC2 || 24C32ASN || SO-08 || ST 24C32 MN6 |- | 2 || R3, R4 || 3k3 || R0603 || RND 0603 1 3,3K |} Aktuell gibt es noch keine weitere Unterstützung hierfür. Es handelt sich also eher um ein Gimmick. Den EEProm kann man sich recht günstig von eBay-Modulen "abernten" - einfach im nächsten Abschnitt weiterlesen. ==Real-Time-Clock== '''Aufgebaut und erfolgreich getestet.''' Da die Pirozeda-Software für das Logging eine gültige Uhrzeit benötigt, und es nach einem Stromausfall nicht sichergestellt ist, dass sich der Pi sofort nach dessen Start synchronisieren kann, kann eine RTC bestückt werden: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R11, R12 || 0 || R0603 || RND 0603 1 0 |- | 1 || C8 || 100n || C0603 || X7R-G0603 100N |- | 1 || B1 || 3003 || 3003 || KZH 20P |- | 2 || R6, R8 || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || IC1 || DS1307Z || SO08 || DS 1307Z |- | 1 || Q5 || TC38_SMD || TC38H_SMD || AUR Q-32.768000K |} Es ist noch anzumerken, dass der DS1307Z laut Datenblatt auch 3,3 V als IO-Spannung unterstützt. Zur Sicherheit habe ich für jedoch einen Levelshifter eingebaut (R5, R6, R7, R8, Q3, Q4), der jedoch durch die 0R-Widerstände R11 und R12 ersetzt werden kann. Der Levelshifter kann nach ersten Testes getrost weggelassen werden. Wem der DS1307 bei Reichelt zu teuer ist, kann sich bei eBay ein Modul mit dem Chip, passendem Quarz (der zufällig dem verwendeten entspricht) und einem ebenfalls passenden EEProm besorgen. Der Batteriehalter passt im aktuellen Design leider nicht. <gallery> EBay-RTC-Module.jpg|RTC-Modul als Bauteilspender </gallery> ==Option: I²C(-OLED) + Taster== '''Noch nicht aufgebaut und getestet.''' Um noch weitere I²C-Devices anzuschließen, ist der Port auf eine Buchsenleiste herausgeführt. Diese ist so ausgerichtet, dass z. B. eines dieser 0,96" 128x64 Pixel OLEDs direkt angeschlossen werden kann. Da wohl teilweise VCC und GND vertauscht sind, kann durch Drehen von R29 und R30 die Polarität geändert werden: <gallery> pirozeda_hat_0.1_i2c_polarity.png|Bestückungsvarianten für unterschiedliche Polarität der Versorgung </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R29, R30 || 0 || R0603 || RND 0603 1 0 |- | 1 || SV3 || FE04-1R || FE04-1R || MPE 094-1-004 |} Ferner gibt es Platz für einen Taster, der GPIO22 mit Masse verbinden kann. Damit es im Falle einer Fehlkonfiguration nicht zu einem harten Kurzschluss kommt, ist ein 100 Ohm-Widerstand vorgesehen: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || R31 || 100 || R0603 || RND 0603 1 100 |- | 1 || S1 || KMR2 || KMR231GLFS || KMR 231 G LFS |} ==Status-LEDs== '''Aufgebaut und erfolgreich getestet.''' Macht einfach drauf was ihr wollt, solange es LEDs im 0603-Package sind und der Vorwiderstand (im 0603-Package) dazu passt. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 3 || R24, R25, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || LED1 || gn || CHIP-LED0603 || |- | 2 || LED2, LED3 || or || CHIP-LED0603 || |} LED1 (mitte) zeigt Aktivität an, LED2 (unten) ist mehr oder weniger die Power-LED. Mehr oder weniger, da sie beim Start der Firmware aktiviert wird (nicht aber im Bootloader). Dadurch kann man sehr schnell erkennen, ob sich die Hardware in einem Bootloop befindet. LED3 (oben) kann vom Raspberry Pi angesteuert werden. Standardmäßig sind in der <code>config.h</code> folgende Zeiten für LED1 eingestellt: * Start der Anwendung: 250 ms * Korrekt empfangene Nachrichten: 10 ms * Fehlerhaft empfangene Nachrichten: 200 ms Damit kann man auf den einen Blick erkennen, ob Daten vernünftig ankommen und verarbeitet werden können. =Aufbau der Hardware= ==Bestücken der Leiterkarte== Die Hardware kann im Prinzip in beliebiger Reihenfolge aufgebaut werden. Trotzdem ist es ratsam, die großen/hohen Bauteile zuletzt aufzulöten. Die Steckkräfte einer 2x20 Buchsenleiste sind vergleichsweise groß. Diese können reduziert werden, indem nicht verwendete Pins aus der Buchsenleiste entfernt werden. Um diese nicht wieder (fragt nicht) zurückstecken zu müssen, hier eine Auflistung der benötigten Pins: 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 15, 17, 20, 25, 27, 28, 30, 34, 37, 39. Oder einfach als Bild: <gallery> Pirozeda_hat_0.1_buchsenleiste_pins.png|benötigte Pins (blau markiert) </gallery> Der Wannenstecker lässt sich am einfachsten auflöten, wenn man die Pads auf einer Seite (egal welche) der Leiterkarte bisschen stärker verzinnt. Dadurch kann man den Konnektor ein wenig verklemmen und vor dem Verlöten besser ausrichten. ==Zuleitung== Als Zuleitung habe ich für die ersten Muster den Artikel LIYY 614 (Steuerleitung 6x0,14mm², ungeschirmt) von Reichelt verwendet. Beim Bestellen habe ich leider mehr auf den Preis als die Schirmung geachtet. In Hinblick darauf, dass der Schirm der Buchse im Regler eh nicht mit Masse verbunden ist, ist es eine ziemliche Fummelarbeit, diese mit dem Massepin zu verbinden. Erkenntnisse über die maximale Leitungslänge gibt es noch nicht. Der Vorteil dieser Leitung ist: die Adern können direkt im Pfostenverbinder verpresst werden: <gallery> Pirozeda_hat_0.1_pfosten.jpg </gallery> Ich habe mich für folgende Farbgebung entschieden, beim Pinmapping selbst gibt es keine Wahl: {| class="wikitable" ! Mini-DIN || Signal || Farbe || Wannenstecker |- | 3 || MISO || grau || 1 |- | 4 || GND || braun || 3 |- | 5 || 3V3 || rosa || 5 |- | 6 || MOSI || grün || 2 |- | 7 || SCK || gelb || 4 |- | 8 || !CS || weiß || 6 |} Beim Mini-DIN-Stecker sollte darauf geachtet werden, die äußere Hülle nicht komplett über den Rest zu stülpen, da die Buchse beim Regler ziemlich weit nach innen versetzt ist: <gallery> Pirozeda_hat_0.1_minidin.jpg </gallery> =Firmware= Grundsätzlich läuft die Firmware des Originaldesign auch mit der HAT-Hardware. Allerdings bleiben die LEDs dunkel und viele neue Features fehlen: Ab 0.2: * Status-LEDs * Uptime-Counter * Messung der Versorgungsspannung * Anzeigen von Bootinformationen ** Resetgrund ** Anzahl der vorherigen Reboots ** Dauer der vorherigen Uptime ** Fusecheck ** Watchdog-Info ** Aktivierte Nachrichten * Neustart + Wechsel in den Bootloader per Kommando * Statistik über empfangene Nachrichten (optional) * Timestamps (optional, aktuell nicht kompatibel mit der Backend-Software) * Erneutes übertragen der Headerinformationen * Kann die Firmware bei einem "Katzen-Paket" miauen. Einfach nur weil. ==Konfiguration== Einige der Features müssen vor dem Kompilieren aktiviert bzw. eingestellt werden. Die Schalter und Defines hierfür befinden sich in zwei Header-Dateien: <code>config.h</code> * <code>PIROZEDA_KITTY_DEBUG</code>: Anzeigen der "Katzen-Pakete" (Vorgabe: inaktiv) * <code>PIROZEDA_TIMESTAMPS</code>: Anzeigen der Timestamps (Vorgabe: inaktiv) * <code>PIROZEDA_WDT_TIMEOUT</code>: Timeout des Watchdogs (Vorgabe: 4 s) * <code>PIROZEDA_UPTIME</code>: Führen der Uptime, abrufbar über den Befehl (Vorgabe: aktiv) * <code>PIROZEDA_SUPPLY_AVGCNT</code>: Anzahl der Messwerte für die Mittelwertbildung der Systemspannung (Vorgabe: 10, maximal: 32) * <code>PIROZEDA_HEADERCNT</code>: Anzahl der Kopfzeilen-Datensätze, die nach dem Start oder Befehl <code>header</code> angezeigt werden (Vorgabe: 200, maximal: 255) * <code>PIROZEDA_STATUS_LED_BOOT</code>: Leuchtdauer der Status-LED nach dem Start (Vorgabe: 100 -> 250 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXOK</code>: Leuchtdauer der Status-LED bei empfangenem Paket (Vorgabe: 4 -> 10 ms, maximal: 255) * <code>PIROZEDA_STATUS_LED_RXERR</code>: Leuchtdauer der Status-LED bei einem Fehler (Vorgabe: 80 -> 200 ms, maximal: 255) * <code>BOOTLOADER_PASSWORD</code>: "Passwort" zum Wechsel in den Bootloader (Vorgabe: "FwUp", maximal 4 Zeichen, darf keine Teilstrings von Befehlen enthalten) <code>prozeda_cfg.h</code> * <code>PROZEDA_USE_COLUMN_NAMES</code>: Verwenden der Spaltennamen (irrelevant für Pirozeda) * <code>PROZEDA_SUPPORT_DISPLAY</code>: Aktiviert den Empfang von Displaydaten (Vorgabe: aktiv) * <code>PROZEDA_SUPPORT_HEADER</code>: Aktiviert den Empfang von Kopfzeilen-Datensätzen (Vorgabe: aktiv) * <code>PROZEDA_IGNORE_KITTY</code>: Ignorieren von Katzen-Paketen, andernfalls werden Fehler ausgegeben (Vorgabe: aktiv) * <code>PROZEDA_MSG_MAXTICKS</code>: Ticks, nach denen ein Paket als abgeschlossen erkannt wird, sollte nur bei Anpassung der CPU-Frequenz angepasst werden (Vorgabe: 3) ==Befehle== Neu ist ab v0.2, dass Befehle an den Mikrocontroller gesendet werden können. Je nach Konfiguration sind dies: * <code>reset</code>: Neustart * <code>uptime</code>: Anzeige der Laufzeit * <code>bootinfo</code>: Anzeigen der Infos, die auch beim (Neu-)Start angezeigt werden * <code>header</code>: Header werden gemäß <code>PIROZEDA_HEADERCNT</code> erneut ausgegeben * <code>stats</code>: Anzeigen der Statistik über empfangene Nachrichten und Empfangsfehler Alle Befehle sind Case-sensitive. ==Flashen der Firmware== Mit den Möglichkeiten steigt die Komplexität. Dadurch dass der die Hardware für die Verwendung mit und ohne Bootloader ausgelegt ist, gibt es mehrere "Pfade" für das Flashen. Wer auf Nummer sicher gehen will, lädt einfach Bootloader und Firmware auf den Mikrocontroller herunter. Selbst wenn man "nur" die Variante mit unidirektionalem UART hat - die Brücken Versorgung und für den UART zum Mikrocontroller ist schneller gelötet als die Stiftleiste für den ISP-Port. Das Einlöten einer wahnsinnig hohen Stiftleiste kann übrigens umgangen werden, indem eine Stiftleiste in das Programmierkabel gesteckt und im Footprint der Buchse "verkeilt" wird. Wirklich keine Dauerlösung aber im Idealfall muss man es nur einmal machen. ===Über Raspberry Pi=== Zunächst muss, wenn nicht schon geschehen, über <code>sudo raspi-config</code> das SPI-Interface aktiviert (reboot nicht vergessen) und [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer#Installation_der_Compiler AVRDUDE installiert] werden. Den Regler vom HAT trennen, nicht vergessen, dass R10 oder der Hotfix entfernt werden muss, falls der ADuM-Isolator verwendet und einseitig versorgt (also nicht auf dem Raspi steckt) wird und anschließend den SPI-Port mit SV2 verbinden. {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin |- | MISO || 1 || BCM 9 || 21 |- | 3V3 || 2 || 3V3 || 17 |- | SCK || 3 || BCM 11 || 23 |- | MOSI || 4 || BCM 10 || 19 |- | !RES || 5 || BCM 25 || 22 |- | GND || 6 || GND || 20 |} ====Mit Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = FC }} Die empfohlene Variante (auch wenn man nicht beabsichtigt, den Bootloader zu nutzen). Mit Bootloader sind das folgende Befehle: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0xFC:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_fboot_0.2.hex" </source> ====Ohne Bootloader==== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} 'cause I ain't gonna judge you <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"pirozeda_0.2.hex" </source> ==Update der Firmware== In Sachen Bootloader bin ich ein großer Fan von [https://www.mikrocontroller.net/articles/AVR_Bootloader_FastBoot_von_Peter_Dannegger Peter Danneggers Fastboot]. Er ist klein, schnell und zuverlässig. Um einen kleinen Unterschied zu machen, lautet das Passwort zum Starten nicht "Peda" sondern "FwUp", was ein kleines Problem mit sich bringt. "Peda" ist nicht nur der Spitzname vom Autor, das "a" wird zur automatischen Baudratenerkennung verwendet. Das von mir gewählte Passwort hat das nicht zu bieten. Was mir bei der Verwendung von [https://luani.de/projekte/updateloader/ UpdateLoader] aufgefallen ist: es funktioniert trotzdem. Ganz einfach, weil der Autor ein "a" voranstellt. Das funktioniert dann auch mit so gut wie allen anderen Download-Tools. ===Mit Bootloader=== Das Firmware-Update funktioniert nur bei bidirektionaler UART-Kommunikation mit dem Mikrocontroller, also bei der Variante Direkt und ADuM-Isolator. Wenn man mutig ist, kann man bei der Optokoppler-Variante R19 und R27 bestückt werden. In jedem Fall muss die Mikrocontroller-Seite mit Strom versorgt werden, also am einfachsten am Solarregler angeschlossen lassen. Berhard M. (boregard) hat das Programm [https://www.mikrocontroller.net/topic/73196#1067153 lboot] (auch im Download-Paket) geschrieben, das unter Linux mit dem schönen Fastboot von Peter Danegger spricht. Damit der Download funktioniert, muss das Pirozeda-Backend (und andere Software, die auf das UART-Interface zugreift) beendet werden. <source lang="shell"> ./bootloader -d /dev/serial0 -b 115200 -t 1024 -p pirozeda_0.2.hex -P aFwUp </source> ===Ohne Bootloader=== siehe [[#Flashen_der_Firmware]] =Einrichten der Optionen= ==HAT-ID== Wie bereits weiter oben geschrieben, ist der HAT-EEProm momentan eher ein Gimmick als wirklich genutztes Feature. Die Anwendung zur Generierung der Daten kann im [https://github.com/raspberrypi/hats/tree/master/eepromutils GitHub-Repo] vom Raspberry Pi heruntergeladen werden. Da der EEProm im normalen Betrieb schreibgeschützt ist, muss SJ1 gebrückt werden - am besten mit einem guten Klecks Lötzinn. Anschließend kann mit dem Script eepflash.sh (liegt dem Download-Paket bei) das EEProm-Image geschrieben werden: <source lang="bash"> sudo ./eepflash.sh -w -f=pirozeda-hat_id.eep -t=24c32 -a=50 </source> Aktuell sind weder Product-ID noch Version-ID vergeben, ansonsten ist die Konfiguration wie folgt: <pre> # Start of atom #0 of type 0x0001 and length 60 # Vendor info product_uuid 9edc3aef-683c-4007-b2f2-3ea4969b1737 product_id 0x0000 product_ver 0x0000 vendor "hobbyelektronik.org" # length=19 product "Pirozeda HAT v0.1" # length=17 # End of atom. CRC16=0x9a75 # Start of atom #1 of type 0x0002 and length 32 # GPIO map info gpio_drive 0 gpio_slew 0 gpio_hysteresis 0 back_power 0 # GPIO FUNCTION PULL # ---- -------- ---- setgpio 22 INPUT UP setgpio 26 OUTPUT NONE </pre> ==RTC== Die [http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-RTC/index.html Netzmafia] hat einen recht guten Artikel, wie man die hwclock bedient. Wer sich nicht einlesen will, hier im Schnelldurchlauf: Testen der RTC: <source lang="shell"> #call bash as superuser, this is needed to get the echo working properly sudo bash modprobe rtc-ds1307 echo "ds1307 0x68" > /sys/class/i2c-adapter/i2c-1/new_device #Auslesen der Uhr hwclock --debug -r exit </source> Dauerhaftes aktivieren der RTC: <source lang="shell"> sudo bash # enable module echo "# enable DS1307-RTC" >> /etc/modules echo "rtc-ds1307" >> /etc/modules # remove fake-hwclock update-rc.d -f fake-hwclock disable update-rc.d -f fake-hwclock remove apt-get remove fake-hwclock # overwrite prepared configuration of hwclock cp /etc/init.d/hwclock.sh ./hwclock.old cat ./hwclock.new > /etc/init.d/hwclock.sh # enable start/stop script update-rc.d hwclock.sh enable exit </source> Laut Anleitung von Netzmafia muss die Datei <code>/etc/init.d/hwclock.sh</code> noch wie folgt angepasst werden: <source lang="text"> Nun muss noch das Start/Stopp-Script für die RTC angepasst werden. Dazu wird (als root-User) die Datei /etc/init.d/hwclock.sh mit dem Editor bearbeitet. Zunächst tragen Sie am Anfang des Scripts die Default-Wert ein bzw. überprüfen diese: # These defaults are user-overridable in /etc/default/hwclock BADYEAR=no HWCLOCKACCESS=yes HWCLOCKPARS=' --noadjfile --utc' HCTOSYS_DEVICE=rtc0 Nach der Zeile 'case "$1" in start)' werden die folgenden drei Zeilen auskommentieren ('#' davorsetzen): #if [ -d /run/udev ] || [ -d /dev/.udev ]; then # return 0 #fi </source> Um das zu vereinfachen, habe ich eine SH-Datei vorbereitet, natürlich muss sich diese (<code>hwclock.new</code>) im gleichen Verzeichnis liegen, damit es funktioniert. Im Ordner <code>options/rtc</code> befindet sich sowohl die <code>rtc-test.sh</code> als auch <code>rtc-enable.sh</code>. Da diese über meinen Windows-PC gewandert sind und dadurch ihre Dateieigenschaften verloren haben, müssen sie entweder als ausführbar markiert werden oder mit <code>/bin/bash</code> gestartet werden: <source lang="shell"> sudo /bin/bash rtc-test.sh </source> ==I²C + Taster== Für die Verwendung des I²C muss eigentlich nur in <code>raspi-config</code> das I²C-Interface aktiviert werden. Mit der Konfiguration im ID-EEPRom wird der Taster in den Device-Tree eingebunden, allerdings kann er prinzipiell auch ohne angesprochen werden. =Backend= Das Back- und Frontend aus [[Pirozeda]] kann prinzipiell weiterverwendet werden. Es gibt allerdings noch keinen Support der neuen Features. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Mechanik= Im [[3D-Druck-Sammelsurium]] gibt es einen Spacer zwischen Raspberry Pi Zero und dem Hat. =Verbesserungsmöglichkeiten= * Korrektur der Reset-Beschaltung * ESD-Schutz hinzufügen. Aktuell können auf den Footprints von C7, C11 und C14 ESD-Schutzdioden wie B72500D50A60 von Reichelt bestückt werden. Allerdings ist die Positionierung nicht ideal * Stiftwanne für den SPI-Schnittstelle oben auf der Leiterkarte platzieren * Die Widerstände für die Direktverbindung so platzieren, dass sie für das Bootloader-Update einfacher bestückt werden können (oder gleich Jumper) * Hinzufügen der Batteriehalter der billigen RTC-Module (Recycling FTW!) * Entfernen des nicht benötigten I²C-Levelshifters * Vermeiden von Backfeed in der Direkt-Variante * Korrektur des fehlerhaften Footprints für den Raspberry Pi Zero (untere Löcher um 0,5 mm nach unten versetzt) =Download= [[Datei:Pirozeda_hat.zip]] enthält: * Designdaten im EAGLE-Format * Quellen des Bootloaders von Peter Dannegger * Quellen der Firmware + flashbare Images * Scripts für die Einrichtung der Optionen [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 97250aa9a5835ad11561e0377db5d3bc462a1d1f MCP-USB-Bridge 0 514 1410 1394 2020-02-15T21:45:26Z Chris 2 wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-I²C-Bridge v1.1= Reichelt hat den 23B-500 aus dem Programm genommen. Wer ihn bestellen will, fällt wahrscheinlich auf den 23B-500K herein, der leider 3 Zehnerpotenzen daneben liegt. Das und die relativ schlecht einstellbare IO-Spannung (Bereich und Präzision) hat mich dazu bewogen, das Design abzuwandeln. Neben einem neuen Regler (der leider etwas weniger Strom kann) und Präzisionstrimmer gibt es nun zwei Montagelöcher. Letztere haben leider eine relativ schlechte Clearance zu den Bauteilen. Arg viel besser geht es in diesem Formfaktor leider nicht... Als weiteres Goodie sind jetzt auch die GPIOs (wenn auch sehr klein) beschriftet: <gallery> Mcp2221_usb-i2c_1.1_sch.png|Schaltplan Mcp2221 usb-i2c v1.1 top.png|Bestückungsplan oben Mcp2221 usb-i2c v1.1 bot.png|Bestückungsplan unten Mcp2221 usb-i2c v1.1 assy.jpg|Foto der (größtenteils) aufgebauten Leiterkarte </gallery> Die BOM ist entsprechend fast gleich: {| class="wikitable" ! Menge || Referemz || Wert || Package || Reichelt Bestellcode |- | 1 || JP3 || || JP2Q_NN || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2NN || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C7 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R17 || 200k || S64Y || 64Y-200K |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || C6 || 4u7 10V || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 56k || R0603 || RND 0603 1 56K |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || IC3 || TPS76301 || SOT23-DBV || TPS 76301 DBVR |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Hinsichtlich der BOM gibt es auch ein ziemliches Problem: Reichelt hat die eigentlichen Standardwerte 0603 100 nF, 0603 470 nF, 0805 1 µF/16 V aktuell (02/2020) gar nicht mehr im Programm, die USB-Buchse habe ich bis jetzt noch nie lieferbar gesehen. Auch wenn sich die Probleme einfacher umgehen lassen - was zum ... ist da los? =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. * '''Achtung''': Unter Python >= 3.8 gibt es aktuell wohl keine "wunschlos glücklich" hidapi-Lib. Zumindest bei meinen Versuchen wollte das Teil beim Installieren nicht bauen. Workaround: Python 3.7 verwenden. Deshalb: es wird eine Version 2 geben. Das Datenblatt des MCP2221 enthält ein paar Fehler bzw. fehlen Informationen: * Die Berechnung der I²C-Clock ist eher ungenau * Es fehlen wichtige Informationen zu den Zuständen der Statemachines, die Microchip auch auf Rückfrage nicht herausrücken wollte, für die Implementierung aber zwingend erforderlich sind. Hier musste ich mutmaßen * Im Befehl zum Setzen der SRAM-Settings ist der angegebene Wert zum Schreiben der GPIO-Settings (Byte 7) falsch * Das Umstellen der ADC-Referenz muss nach dem Setzen der Pinfunktion erfolgen, da sonst die Referenz auf den Default-Wert gesetzt werden =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =C#-Lib= Um auch aus C# heraus und nicht (wie mit der Lib von Microchip) an ein .NET-Framework gebunden zu sein, habe ich auch eine Bibliothek sowohl für den MCP2221 als auch MCP2210 in nativem C# (ohne externe DLLs oder sonstige Abhängigkeiten) geschrieben. Einige, für den täglichen Bedarf weniger benötigte, Funktionen wurden ausgelassen; die Performance ist zumindest bei I²C ähnlich gut wie die der Python-Lib. Codebeispiele und entsprechende Anwendungen werden folgen, sobald ich Zeit habe, sie zu vervollständigen. Der unvollständige "Release" ist einfach nur, damit der Code unter die Leute gemischt wird :) Folgende Demos ist aktuell vorbereitet (oder geplant): * MCP2221 ** ADC/(DAC) ** TI INA219 - Current Shunt & Power Monitor ** (TI INA3221 - 3Ch Current Shunt & Power Monitor) ** Microchip MCP4725 - 12-Bit-DAC ** QMC5883L - Magnetometer ** (STM LSM-irgendwas - 6D-Sensor mit Schrittzähler) ** (Atmel/Microchip Maxtouch-Touchcontroller) ** (Avago/Broadcomm APDS-99x0 - Ambient light/Gesten-/Farb-Sensor) * MCP2210 ** Maxim MAX31855 - K-Typ Temperatursensor ** Maxim MAX7219 - LED-Treiber ** Nordic Semi nRF24L01+ - 2,4 GHz Transceiver (+ [https://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/ BLE-Hack], der Logitech-Hack ist aktuell nicht geplant) ** (TI CC1101 - Low-Power Sub-1 GHz RF Transceiver) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Backplate= Im [[3D-Druck-Sammelsurium]] gibt es Backplates zum Selberdrucken =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= * [[Datei:mcp22xx_py.zip]] Python3-Lib v0.2, aktuell nur für MCP2221, mit Beispielen * [[Datei:Mcp22xx cs.zip]] C#-Lib v0.1, für MCP2221 und MCP2210, aktuell noch ohne Beispiele und teilweise ungetestet * [[Datei:MCP-USB-Bridge.zip]] enthält: ** Designdaten beider Boards (jeweils Version 1.0) im EAGLE-Format * [[Datei:mcp-usb-i2c_v1.1.zip]] enthält Version 1.1 des USB-I²C-Adapters im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 01a37ab46d997e56f089c1b96416a9bf0bc0c726 Datei:Mcp-usb-i2c v1.1.zip 6 609 1411 2020-02-15T21:45:42Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Mcp2221 usb-i2c v1.1 assy.jpg 6 610 1412 2020-02-15T21:46:22Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Mcp2221 usb-i2c v1.1 bot.png 6 611 1413 2020-02-15T21:46:37Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Mcp2221 usb-i2c v1.1 top.png 6 612 1414 2020-02-15T21:46:44Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Mcp2221 usb-i2c 1.1 sch.png 6 613 1415 2020-02-15T21:46:50Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Hauptseite 0 1 1416 1393 2020-02-15T21:50:30Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert e8bafcac9cb7b66a6e2b154ee6f7c9ec53fae801 1430 1416 2020-03-01T17:42:37Z Qsysopr 1 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] e23978c73c90478f7bd0bd04263972e45509c38c Datei:Footswitch 1.0 assy.jpg 6 614 1417 2020-03-01T17:35:25Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Footswitch 1.0 bot.png 6 615 1418 2020-03-01T17:35:33Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Footswitch 1.0 designflaw 1.jpg 6 616 1419 2020-03-01T17:35:41Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Footswitch 1.0 designflaw 2.jpg 6 617 1420 2020-03-01T17:35:45Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Footswitch 1.0 designflaw 3.jpg 6 618 1421 2020-03-01T17:35:53Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Footswitch 1.0 top.png 6 619 1422 2020-03-01T17:36:05Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Footswitch 1.0 sch.png 6 620 1423 2020-03-01T17:36:20Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Footswitch.jpg 6 621 1424 2020-03-01T17:36:55Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Footswitch gamepad.png 6 622 1425 2020-03-01T17:37:17Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 USB-Fußtaster 0 623 1426 2020-03-01T17:38:05Z Chris 2 Seite erstellt wikitext text/x-wiki [[Datei:Footswitch.jpg|thumb|Fertig aufgebauter Fußtaster]] "Schau Mama, freihändig!" Wer kennt das nicht? Man muss auf mehreren Leiterkarten verschiedene Spannungen messen. Üblicherweise läuft es dann wie folgt ab: # Messspitzen platzieren # Wert vom Messgerät ablesen # Messspitzen ablegen und zum PC umdrehen # Messwert eintippen # Zurückdrehen, Messspitzen wieder in die Hände nehmen # Nochmal nachschauen, welcher Messpunkt jetzt dran ist # Wiederholen Ab und zu mischt sich dann das erneute Messen ein, weil ein Wert unplausibel ist und man entweder einen Zahlendreher drin oder schneller getippt als gedacht hat. Unterm Strich ist es auf jeden Fall sehr zeitraubend und nervig. Gleichzeitig baumeln die Füße unbeteiligt am Stuhl herunter. Die meisten Messgeräte (und anderes Laborequipment) lassen sich über den PC kontrollieren, warum also nicht gleich die richtigen Werte z. B. nach Excel transferieren? Nur irgendwie muss man den Prozess anstoßen... =Die schnelle Lösung= Tastatur ist blöd, also muss eine andere Eingabemöglichkeit her. Ein Taster und eine Projektbox ist schnell gefunden, Loch in die Box und ein paar große Schrauben dazu (damit sie nicht gleich abhaut) und fertig ist der improvisierte Fußtaster. Nur wie kommt die Info in den PC? Die serielle Schnittstelle hat neben Rx und Tx oft auch Steuerleitungen – aus den alten Tagen, in denen Modems noch so richtig langsam waren. Diese lassen sich in so ziemlich jeder Programmiersprache kontrollieren und abfragen. Ein FT232 liegt auch noch herum, also Taster angelötet und los geht’s! Das Programm ist in Python geschrieben, pollt die CTS-Leitung und sobald diese low wird, wird per pyVisa den Multimeter der aktuelle Messwert entlockt, passend formatiert und mit dem Keyboard-Modul "ausgetippt". Damit die Augen am Mikroskop bleiben können, wird zudem ein kurzer Piepton ausgegeben. Sehr viel Spaß für wenig Geld. Leider muss man bei jeder Benutzung schauen, welcher COM-Port dem Adapter zugeordnet wurde und ob dieser auch wirklich im Script steht. =Die schöne Lösung= Eines Tages brachte mein Kollege einen kleinen Pappkarton vom [https://www.pollin.de Ramschmax] mit, Inhalt: [https://www.pollin.de/p/fusstaster-pfs-135a-10-a-250-v-420705 420705]. Ein Gusseiserner Fußtaster mit schönem Klick-Klack-Mikroschalter. Der hat etwas besseres als den schnöden UART-Adapter mit Zwillingslitze verdient – endlich wieder eine schöne Anwendung für [https://www.obdev.at/vusb/ V-USB]! Was soll das Teil können? Am besten natürlich so viel wie möglich, damit es vielleicht sogar als "Adaptive Controller" dienen kann. Deshalb habe ich mich dafür entschieden, einen Multidevice-Ansatz zu fahren. Das umfasst aktuell: * Generisches USB-HID * Einzeltasten-Tastatur * Makro-Tastatur * Joystick =Hardware= Die Hardware könnte nicht einfacher sein - sie entspricht größtenteils dem [https://www.obdev.at/products/vusb/easylogger.html Easylogger]-Beispielprojekt, nur dass anstelle der automatischen Oszillator-Kalibrierung ein externer Quarz verwendet wird. Hintergrund hierfür ist, dass das [[SNES-Joypad]], das sich selbst kalibriert (oder zumindest sollte), am RetroPie beim Booten oft nicht erkannt wird. Kann aber auch gut sein, dass es sich um einen Bug in meiner Firmware handelt. Die Bauteile sind - abgesehen vom Quarz und Mikrocontroller in SMD-Bauform. Als MCU werkelt fürs Erste ein ATtiny85, der später noch herunterskaliert werden kann. Die Wahl auf das DIP-Gehäuse fiel, um ohne Löten die Firmware herunterzuladen. Mit Quarz als Taktquelle bleibt noch ein "richtiger" IO übrig (sofern man den Reset-Pin nicht deaktiviert) - mehr braucht man nicht. Eine eigens designte Leiterkarte ist aufgrund der Einfachheit der Schaltung völlig unnötig, aber es war noch Platz auf dem Panel... <gallery> footswitch 1.0 sch.png|Schaltplan footswitch 1.0 top.png|Bestückungsplan Oberseite footswitch 1.0 bot.png|Bestückungsplan Unterseite footswitch 1.0 assy.jpg|Aufgebaute Leiterkarte </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || MA03-1 || |- | 1 || SV1 || || MA04-1 || GC 2212-EU030 |- | 1 || C1 || 100n || C0603 || X7R-G0603 100N |- | 1 || C4 || 10u || C0805 || KEM X7R0805 10U |- | 1 || Q1 || 12M || HC49U-V || 12,0000-HC49U-S |- | 1 || R11 || 150 || R0603 || RND 0603 1 150 |- | 1 || C5 || 150n || C0603 || X7R 0603FCE 150N |- | 2 || C2, C3 || 22p || C0603 || RND 150MT18N2202 |- | 1 || R3 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || R10 || 4k7 || R0603 || RND 0603 1 4,7k |- | 2 || R1, R2 || 68 || R0603 || RND 0603 1 68 |- | 1 || IC1 || ATTINY 85-20 PU || DIL08 || ATTINY 85-20 PU |- | 2 || D1, D2 || BZX84C3V6 || SOT23 || SMD ZD 3,6 |} Leider stellte sich erst zu spät heraus, dass die Leiterkarte ein bisschen zu groß ist, um sie an der eigentlich vorgesehenen Stelle zu montieren. Man kann sie zwar ein bisschen schräg anschrauben und von der Ecke noch etwas Material wegnehmen, aber dann ist die USB-Leitung auch wieder im Weg. Das Design ist also nicht so richtig geglückt... Aber kein Problem, dass man nicht mit ein bisschen Schrumpfschlauch lösen könnte: <gallery> footswitch 1.0 designflaw 1.jpg|Dort sollte die Leiterkarte hin footswitch 1.0 designflaw 1.jpg|...und hier ist sie footswitch 1.0 designflaw 1.jpg|weitere Perspektive </gallery> Der Schirm ist übrigens auf ein Stück Leitung gecrimpt, das wiederum an die Halterung des Tasters gelötet ist. =Firmware= ==Firmware== {{Infobox AVR | Typ = ATtiny85 | Takt = 12 | FuseH = D7 | FuseL = DE | FuseE = FF }} Die Firmware ist mehr oder weniger viergeteilt, entsprechend den verschiedenen Modi. Hierfür gibt es mehrere Gründe: * die freien VID/PID-Paare sind auf die verschiedenen Funktionen beschränkt und es lässt sich nicht zweifelsfrei sagen, ob Multi-Endpoint-Konfigurationen erlaubt sind * Die Fragmentierung macht den Code (teilweise) einfacher und übersichtlicher * Keinerlei Treiberprobleme (es gibt wohl Betriebssysteme, die sich an Multi-Endpoint verschlucken) * Es ist nicht ganz so üblich und in der Implementierung interessanter Nach dem Reset liest die Firmware den zu verwendenden Modus aus dem EEPROM. Ist diese ungültig oder der IO des Tasters auf Masse gezogen, wird der auf Generisches HID gesetzt. Gegenüber des USB-Treibers wird nun auch der Pointer für die USB-Deskriptoren gesetzt (die sich wiederum im Flash befinden). Anschließend läuft die Initialisierung der unterschiedlichen Modi und es wird in die entsprechende Endlosschleife gesprungen. Als USB VID/PID-Paare werden von obdev frei zur Verfügung gestellten verwendet: * HID: 0x16C0/0x27D9 * Tastatur: 0x16C0/0x27DB * Gamepad: 0x16C0/0x27DC Im Grunde ist das alles kein Hexenwerk, allerdings haben die "Dynamisierung" der USB-Deskriptoren einiges an (auf dem Attiny schwierige) Fehlersuche gekostet. Über Manche Dinge, wie z. B. wie man die verschiedenen Deskriptoren den Anfragen zuordnet, ist die Dokumentation leider etwas vage (oder ich habe sie nicht richtig gelesen/falsch gesucht). Auch lässt sich die Firmware noch ziemlich optimieren, das gesteckte Ziel wäre, dass sie auf den ATtiny45 passt. Aktuell ist hauptsächlich die RAM-Belegung ein Problem (und noch nicht optimal). =Konfiguration= Um die Konfiguration des Fußtasters ändern zu können, muss er sich in Modus 2 (Generisches HID) befinden. Sollte dieser Modus nicht aktiv sein, kann er erreicht werden indem der Taster gedrückt wird, während der USB-Stecker verbunden wird. In den Report-Besispielen werden stats hexadezimale Zahlen verwendet. Angaben mit <code>xx</code> sind beliebig bzw. müssen ignoriert werden. ==Keycodes== Bevor auf die verschiedenen Funktionen im Detail eingegangen wird, ein paar Worte zu den Keycodes: Tastaturen sind seit jeher ziemlich einfach gestrickt. So "weiß" der Controller der Tastatur zwar an welcher Position eine Taste gedrückt wird, aber nicht welches Layout sie vertritt - dies wird erst durch das Betriebssystem umgestzt. Das hat zum Beispiel den Effekt, dass mit einer deutschen Tastatur an einem auf englisch eingestellten PC u. a. Y und Z vertauscht sind (und man beim Raspberrz Pi das Passwort mindestens einmal falsch eingibt). Diese Eigenschaft betrifft natürlich auch den Fußtaster. Die Keycodes für englische Tastaturen können in der Spezifikation [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 "Universal Serial Bus HID Usage Tables"] in der aktuellen Version ab Seite 53 (Kapitel 10 Keyboard/Keypad Page (0x07)]) nachgeschlagen werden. Für das deutsche Layout befindet sich eine Tabelle im Download-Bereich (keine Garantie auf Vollständigkeit und Korrektheit). ==Modus 0: Generisches HID== Die Kommunikation findet über Report ID 0 mit 8 Datenbytes statt. Beim Senden von Reports definiert das erste Byte den Befehl, in den weiteren befinden sich die Parameter dessen: {| class="wikitable" ! Nummer || Befehl || Beschreibung |- | 0 || NOP || Keine Operation, dieser Code wird bei den Antworten für den Status des Tasters verwendet |- | 1 || Restart || Neustart des Mikrocontrollers (ersetzt das Aus- und Einstecken nachdem der Modus umgestellt wurde) |- | 2 || Lesen Modus || Gibt den Interface-Modus zurück |- | 3 || Setzen Modus || Setzt den Interface-Modus |- | 4 || Lesen Einzeltaste || Gibt den Keycode der Einzeltasten-Tastatur zurück |- | 5 || Setzen Einzeltaste || Setzt den Keycode der Einzeltasten-Tastatur |- | 6 || Lesen Tastensequenz || Gibt 6 Byte der Sequenz des angegebenen Blocks (in Byte 1) zurück |- | 7 || Setzen Tastensequenz || Setzt die 6 Bytes der Sequenz des angegebenen Blocks (in Byte 1) |} Jeder Befehl wird beantwortet, wobei dem ersten Byte eine Statusinformation mit bitweise Oder hinzugefügt wird: {| class="wikitable" ! Nummer || Status || Beschreibung |- | 0x00 || None || Wird nicht verwendet |- | 0x40 || Busy || Der Befehl wurde nicht ausgeführt, weil der Controller beschäftigt ist |- | 0x80 || Ok || Der Befehl wurde erfolgreich ausgeführt, die optionale Antwort befindet sich in den restlichen Bytes |- | 0xC0 || Error || Beim Ausführen des Befehls ist ein Fehler aufgetreten |} ===Tastenstatus=== Für jede Änderung des Tastenstatus wird ein Report übertragen: <code>&lt; <span class="hb1">00</span> <span class="hb2">BB</span> xx xx xx xx xx xx</code> * <span class="hb1">"Befehl": Status der Taste</span> * <span class="hb2">Status der Taste - 0: nicht gedrückt, 1: gedrückt</span> ==Modus 1: Einzeltasten-Tastatur== In diesem Modus verhält sich der Fußtaster wie die Taste einer Tastatur. Die zu drückende Taste kann über Modus 2 festgelegt werden. Leider ist es aktuell noch nicht möglich, Multimedia-Tasten (Wiedergabesteuerung, Lautstärke, Anwendungssteuerung) zu verwenden. ===Lesen=== Zum Zurücklesen der verwendeten Taste muss folgender Report gesendet werden: <code>&gt; <span class="hb1">04</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste</span> Die Antwort entspricht folgendem Muster: <code>&lt; <span class="hb1">84</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste (OK)</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) ** 0x01: Steuerung links ** 0x02: Umschalttaste links ** 0x04: Alt links ** 0x08: GUI links (u. a. Windows-Taste) ** 0x10: Steuerung rechts ** 0x20: Umschalttaste rechts ** 0x40: Alt rechts (müsste Alt+Gr sein) ** 0x80: GUI rechts (müsste Kontextmenü sein) * <span class="hb3">Keycode Taste</span> ===Schreiben=== Zum Setzen einer Taste folgender Report gesendet werden: <code>&gt; <span class="hb1">05</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Setzen Einzeltaste</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) * <span class="hb3">Keycode Taste</span> Die restlichen Bytes im Report werden ignoriert. Die Bestätigung wird wie unter "Modus 2" beschrieben gesendet. Da keine Readback stattfindet, wird immer mit "OK" geantwortet: <code>&lt; <span class="hb1">85</span> xx xx xx xx xx xx xx</code> ==Modus 2: Makro-Tastatur== Über die Makro-Tastatur können längere Tastenfolgen ausgegeben werden. Für diesen Zweck sind 128 Byte im EEPROM vorgesehen, was einer maximalen Folge von etwa 63 Anschlägen entspricht. Aktuell kann nur eine Taste gleichzeitig gedrückt werden kann - ein Rollover ist dementsprechend nicht möglich. Die Ausgabe erfolgt mit maximaler Geschwindigkeit, also mit etwa 100 Anschlägen pro Sekunde, wobei zwischen gleichlautenden Anschlägen sowie nach dem letzten Zeichen automatisch ein Loslassen der Taste eingefügt wird, was zu einer kleinen Verzögerung führt und damit das Timing verändert Beispiel: Bei der Ausgabe des Wortes <code>Hallo</code> folgende Reports übertragen: * Umschalttaste drücken, Taste "H" drücken * Umschalttaste loslassen, Taste "A" drücken * Taste "L" drücken * Taste "L" loslassen * Taste "L" drücken * Taste "O" drücken * Taste "O" loslassen So dauert die Übertragung des Wortes - bei einem Report-Intervall von 10 ms - etwa 70 ms statt den zunächst anzunehmenden 50 ms. ===Datenformat=== Die Daten werden im Muster <code>Befehl + Daten</code> gespeichert, wobei die Datenlänge dynamisch (aber anhand des Befehls ersichtlich) ist. Dementsprechend sind die Befehle teilweise als Flags aufgebaut, zum besseren Verständnis hier im Binärformat: * <code>0b<b>11111111</b></code>: Ende der Sequenz (entspricht nicht beschriebenen Speicherzellen), keine Daten * <code>0b<b>1</b><span class="hb1">ppppppp</span></code>: Pause in 5 ms-Schritten, p = 0 ... 126, t = (p + 1) * 5 ms, maximal 635 ms, keine Daten * <code>0b<b>0</b><span class="hb2">mm</span><span class="hb3">xx</span>xxx</code>: Verhalten der Modifier ** <code><span class="hb2">0b00</span></code>: Modifier beibehalten, keine Daten ** <code><span class="hb2">0b01</span></code>: Modifier für nachfolgende Taste drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb2">0b10</span></code>: Modifier dauerhaft halten, +1 Byte Daten ** <code><span class="hb2">0b11</span></code>: Modifier loslassen, keine Daten * <code>0b<b>0</b><span class="hb2">xx</span><span class="hb3">kk</span>xxx</code>: Verhalten der Taste ** <code><span class="hb3">0b00</span></code>: Taste beibehalten, keine Daten ** <code><span class="hb3">0b01</span></code>: Taste einmal drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb3">0b10</span></code>: Taste dauerhaft halten (bis eine andere Taste gedrückt wird), +1 Byte Daten ** <code><span class="hb3">0b11</span></code>: Taste loslassen, keine Daten Sollen Modifier und Taste mit einem Befehl verändert werden, wird zuerst der Modifier erwartet, dann die Taste: <code>0b0<span class="hb2">10</span><span class="hb3">01</span>000 <span class="hb4">0b00000010</span> <span class="hb5">0b00001011</span> <span class="hb2">Drückt und hält</span> die <span class="hb4">linke Umschalttaste</span> und drückt die <span class="hb5">Taste H (0x0B)</span> <span class="hb3">einmal</span>. Beispiel: Es soll die Zeichenfolge <code>Hallo WELT</code> mit anschließendem Zeilenumbruch ausgegeben werden, mit einer Pause von 500 ms nach "Hallo". Die Sequenz sieht nun wie folgt aus (Binär und Hex gemischt, Hex für Keycodes): {| class="wikitable" ! Code || Befehl || Parameter |- | <code>0b0<span class="hb1">01</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x0B</span></code> || <span class="hb1">Modifier einmal drücken</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Linke Umschalttaste</span>, <span class="hb4">Taste H</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x04</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste A</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x12</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste O</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1100011</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Pause mit 99 Zeiteinheiten</span>: t = (99 + 1) * 5 ms = 500 ms |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb3">0x2C</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Leertaste</span> |- | <code>0b0<span class="hb1">11</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x1A</span></code> || <span class="hb1">Modifier drücken und halten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Rechte Umschalttaste</span>, <span class="hb4">Taste W</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x08</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste E</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x17</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste T</span> |- | <code>0b0<span class="hb1">10</span><span class="hb2">00</span>000</code> || <span class="hb1">Modifier loslassen</span>, <span class="hb2">Kein Tastendruck</span> || - |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x28</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Return-Taste</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1111111</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Ende der der Sequenz</span> |} ===Lesen=== Wie bereits in der Befehlsübersicht erwähnt, erfolgt das Lesen und Schreiben der Sequenzdaten in Blöcken: <code>&gt; <span class="hb1">06</span> <span class="hb2">CC</span> xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> Als Antwort bekommt man dann die Daten des jeweiligen Blocks: <code>&lt; <span class="hb1">86</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Lesen Sequenz (OK)</span> * <span class="hb2">Blocknummer: 0 ... 21 </span> * <span class="hb2">6 Datenbytes des Blocks</span> Ist der letzte Block nicht "füllend", sind die restlichen Bytes zufällig, ebenso kann über das "End of Sequence" hinaus gelesen werden. ===Schreiben=== Das Schreiben von Blöcken ist der Antwort vom Lesen sehr ähnlich: <code>&gt; <span class="hb1">07</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Schreiben Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> * <span class="hb2">6 Datenbytes des Blocks</span> Sobald die Daten geschrieben wurden, antwortet der Mikrocontroller mit: <code>&lt; <span class="hb1">06</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Schreiben Sequenz (OK)</span> ==Modus 3: Gamepad== Es ist keine Konfiguration notwendig, das Gamepad meldet sich mit einer Taste und kann in Anwendungen wie gewohnt zugeordnet werden. <gallery> footswitch_gamepad.png|Eigenschaftenseite in Windows </gallery> Leider erkennt weder Firefox 73 noch Chromium 82 das Pad im html5gamepad-Tester. Anzumerken ist, dass wie bei der Einzeltasten-Tastatur Reports nur bei Zustandsänderung der Taste gesendet werden. Bis jetzt konnte ich dadurch keine Einschränkungen feststellen. =PC-Software= Aktuell gibt es eine kleine Python-Lib und ein paar Beispiele dazu. Siehe Downloads. =Anmerkungen= * Die Firmware auf dem Tiny85 zu entwickeln war grauenvoll, da man nur sehr schlecht debuggen kann. Das nächste Mal lieber auf einem Mikrocontroller mit deutlich mehr IOs und Hardware-UART entwickeln und anschließend auf ein kleineres Geschwister portieren * [https://github.com/micronucleus/micronucleus/ micronucleus] ist ein USB-Bootloader basierend auf V-USB, den ich bis jetzt noch nicht verwendet habe, in Zukunft aber sollte * Der Quellcode steht, wie von objective development gefordert, unter GPLv2 =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= * [[Datei:Footswitch.zip]] Schaltplan & Layout in EAGLE 7.7.0, Firmware & Sourcen in Atmel Studio 7, Beispielanwendung in Python 3.7 =Weblinks= * [https://www.uwe-sieber.de/usbtreeview.html USB Device Tree Viewer] zeigt sehr detaillierte Infos zu angeschlossenen USB-Geräten an * [http://wireshark.org/ Wireshark] kann auch USB tracen * [https://eleccelerator.com/usbdescreqparser/ USB Descriptor and Request Parser] * [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 Universal Serial Bus HID Usage Tables, Seite 53: 10 Keyboard/Keypad Page (0x07)] [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:Kleine Helferlein]] 6471955ca3650e0bfc29becc4a2be9ef3e9d73fb 1428 1426 2020-03-01T17:39:15Z Chris 2 /* Hardware */ Bilderlinks verkackt wikitext text/x-wiki [[Datei:Footswitch.jpg|thumb|Fertig aufgebauter Fußtaster]] "Schau Mama, freihändig!" Wer kennt das nicht? Man muss auf mehreren Leiterkarten verschiedene Spannungen messen. Üblicherweise läuft es dann wie folgt ab: # Messspitzen platzieren # Wert vom Messgerät ablesen # Messspitzen ablegen und zum PC umdrehen # Messwert eintippen # Zurückdrehen, Messspitzen wieder in die Hände nehmen # Nochmal nachschauen, welcher Messpunkt jetzt dran ist # Wiederholen Ab und zu mischt sich dann das erneute Messen ein, weil ein Wert unplausibel ist und man entweder einen Zahlendreher drin oder schneller getippt als gedacht hat. Unterm Strich ist es auf jeden Fall sehr zeitraubend und nervig. Gleichzeitig baumeln die Füße unbeteiligt am Stuhl herunter. Die meisten Messgeräte (und anderes Laborequipment) lassen sich über den PC kontrollieren, warum also nicht gleich die richtigen Werte z. B. nach Excel transferieren? Nur irgendwie muss man den Prozess anstoßen... =Die schnelle Lösung= Tastatur ist blöd, also muss eine andere Eingabemöglichkeit her. Ein Taster und eine Projektbox ist schnell gefunden, Loch in die Box und ein paar große Schrauben dazu (damit sie nicht gleich abhaut) und fertig ist der improvisierte Fußtaster. Nur wie kommt die Info in den PC? Die serielle Schnittstelle hat neben Rx und Tx oft auch Steuerleitungen – aus den alten Tagen, in denen Modems noch so richtig langsam waren. Diese lassen sich in so ziemlich jeder Programmiersprache kontrollieren und abfragen. Ein FT232 liegt auch noch herum, also Taster angelötet und los geht’s! Das Programm ist in Python geschrieben, pollt die CTS-Leitung und sobald diese low wird, wird per pyVisa den Multimeter der aktuelle Messwert entlockt, passend formatiert und mit dem Keyboard-Modul "ausgetippt". Damit die Augen am Mikroskop bleiben können, wird zudem ein kurzer Piepton ausgegeben. Sehr viel Spaß für wenig Geld. Leider muss man bei jeder Benutzung schauen, welcher COM-Port dem Adapter zugeordnet wurde und ob dieser auch wirklich im Script steht. =Die schöne Lösung= Eines Tages brachte mein Kollege einen kleinen Pappkarton vom [https://www.pollin.de Ramschmax] mit, Inhalt: [https://www.pollin.de/p/fusstaster-pfs-135a-10-a-250-v-420705 420705]. Ein Gusseiserner Fußtaster mit schönem Klick-Klack-Mikroschalter. Der hat etwas besseres als den schnöden UART-Adapter mit Zwillingslitze verdient – endlich wieder eine schöne Anwendung für [https://www.obdev.at/vusb/ V-USB]! Was soll das Teil können? Am besten natürlich so viel wie möglich, damit es vielleicht sogar als "Adaptive Controller" dienen kann. Deshalb habe ich mich dafür entschieden, einen Multidevice-Ansatz zu fahren. Das umfasst aktuell: * Generisches USB-HID * Einzeltasten-Tastatur * Makro-Tastatur * Joystick =Hardware= Die Hardware könnte nicht einfacher sein - sie entspricht größtenteils dem [https://www.obdev.at/products/vusb/easylogger.html Easylogger]-Beispielprojekt, nur dass anstelle der automatischen Oszillator-Kalibrierung ein externer Quarz verwendet wird. Hintergrund hierfür ist, dass das [[SNES-Joypad]], das sich selbst kalibriert (oder zumindest sollte), am RetroPie beim Booten oft nicht erkannt wird. Kann aber auch gut sein, dass es sich um einen Bug in meiner Firmware handelt. Die Bauteile sind - abgesehen vom Quarz und Mikrocontroller in SMD-Bauform. Als MCU werkelt fürs Erste ein ATtiny85, der später noch herunterskaliert werden kann. Die Wahl auf das DIP-Gehäuse fiel, um ohne Löten die Firmware herunterzuladen. Mit Quarz als Taktquelle bleibt noch ein "richtiger" IO übrig (sofern man den Reset-Pin nicht deaktiviert) - mehr braucht man nicht. Eine eigens designte Leiterkarte ist aufgrund der Einfachheit der Schaltung völlig unnötig, aber es war noch Platz auf dem Panel... <gallery> footswitch 1.0 sch.png|Schaltplan footswitch 1.0 top.png|Bestückungsplan Oberseite footswitch 1.0 bot.png|Bestückungsplan Unterseite footswitch 1.0 assy.jpg|Aufgebaute Leiterkarte </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || MA03-1 || |- | 1 || SV1 || || MA04-1 || GC 2212-EU030 |- | 1 || C1 || 100n || C0603 || X7R-G0603 100N |- | 1 || C4 || 10u || C0805 || KEM X7R0805 10U |- | 1 || Q1 || 12M || HC49U-V || 12,0000-HC49U-S |- | 1 || R11 || 150 || R0603 || RND 0603 1 150 |- | 1 || C5 || 150n || C0603 || X7R 0603FCE 150N |- | 2 || C2, C3 || 22p || C0603 || RND 150MT18N2202 |- | 1 || R3 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || R10 || 4k7 || R0603 || RND 0603 1 4,7k |- | 2 || R1, R2 || 68 || R0603 || RND 0603 1 68 |- | 1 || IC1 || ATTINY 85-20 PU || DIL08 || ATTINY 85-20 PU |- | 2 || D1, D2 || BZX84C3V6 || SOT23 || SMD ZD 3,6 |} Leider stellte sich erst zu spät heraus, dass die Leiterkarte ein bisschen zu groß ist, um sie an der eigentlich vorgesehenen Stelle zu montieren. Man kann sie zwar ein bisschen schräg anschrauben und von der Ecke noch etwas Material wegnehmen, aber dann ist die USB-Leitung auch wieder im Weg. Das Design ist also nicht so richtig geglückt... Aber kein Problem, dass man nicht mit ein bisschen Schrumpfschlauch lösen könnte: <gallery> footswitch 1.0 designflaw 1.jpg|Dort sollte die Leiterkarte hin footswitch 1.0 designflaw 2.jpg|...und hier ist sie footswitch 1.0 designflaw 3.jpg|weitere Perspektive </gallery> Der Schirm ist übrigens auf ein Stück Leitung gecrimpt, das wiederum an die Halterung des Tasters gelötet ist. =Firmware= ==Firmware== {{Infobox AVR | Typ = ATtiny85 | Takt = 12 | FuseH = D7 | FuseL = DE | FuseE = FF }} Die Firmware ist mehr oder weniger viergeteilt, entsprechend den verschiedenen Modi. Hierfür gibt es mehrere Gründe: * die freien VID/PID-Paare sind auf die verschiedenen Funktionen beschränkt und es lässt sich nicht zweifelsfrei sagen, ob Multi-Endpoint-Konfigurationen erlaubt sind * Die Fragmentierung macht den Code (teilweise) einfacher und übersichtlicher * Keinerlei Treiberprobleme (es gibt wohl Betriebssysteme, die sich an Multi-Endpoint verschlucken) * Es ist nicht ganz so üblich und in der Implementierung interessanter Nach dem Reset liest die Firmware den zu verwendenden Modus aus dem EEPROM. Ist diese ungültig oder der IO des Tasters auf Masse gezogen, wird der auf Generisches HID gesetzt. Gegenüber des USB-Treibers wird nun auch der Pointer für die USB-Deskriptoren gesetzt (die sich wiederum im Flash befinden). Anschließend läuft die Initialisierung der unterschiedlichen Modi und es wird in die entsprechende Endlosschleife gesprungen. Als USB VID/PID-Paare werden von obdev frei zur Verfügung gestellten verwendet: * HID: 0x16C0/0x27D9 * Tastatur: 0x16C0/0x27DB * Gamepad: 0x16C0/0x27DC Im Grunde ist das alles kein Hexenwerk, allerdings haben die "Dynamisierung" der USB-Deskriptoren einiges an (auf dem Attiny schwierige) Fehlersuche gekostet. Über Manche Dinge, wie z. B. wie man die verschiedenen Deskriptoren den Anfragen zuordnet, ist die Dokumentation leider etwas vage (oder ich habe sie nicht richtig gelesen/falsch gesucht). Auch lässt sich die Firmware noch ziemlich optimieren, das gesteckte Ziel wäre, dass sie auf den ATtiny45 passt. Aktuell ist hauptsächlich die RAM-Belegung ein Problem (und noch nicht optimal). =Konfiguration= Um die Konfiguration des Fußtasters ändern zu können, muss er sich in Modus 2 (Generisches HID) befinden. Sollte dieser Modus nicht aktiv sein, kann er erreicht werden indem der Taster gedrückt wird, während der USB-Stecker verbunden wird. In den Report-Besispielen werden stats hexadezimale Zahlen verwendet. Angaben mit <code>xx</code> sind beliebig bzw. müssen ignoriert werden. ==Keycodes== Bevor auf die verschiedenen Funktionen im Detail eingegangen wird, ein paar Worte zu den Keycodes: Tastaturen sind seit jeher ziemlich einfach gestrickt. So "weiß" der Controller der Tastatur zwar an welcher Position eine Taste gedrückt wird, aber nicht welches Layout sie vertritt - dies wird erst durch das Betriebssystem umgestzt. Das hat zum Beispiel den Effekt, dass mit einer deutschen Tastatur an einem auf englisch eingestellten PC u. a. Y und Z vertauscht sind (und man beim Raspberrz Pi das Passwort mindestens einmal falsch eingibt). Diese Eigenschaft betrifft natürlich auch den Fußtaster. Die Keycodes für englische Tastaturen können in der Spezifikation [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 "Universal Serial Bus HID Usage Tables"] in der aktuellen Version ab Seite 53 (Kapitel 10 Keyboard/Keypad Page (0x07)]) nachgeschlagen werden. Für das deutsche Layout befindet sich eine Tabelle im Download-Bereich (keine Garantie auf Vollständigkeit und Korrektheit). ==Modus 0: Generisches HID== Die Kommunikation findet über Report ID 0 mit 8 Datenbytes statt. Beim Senden von Reports definiert das erste Byte den Befehl, in den weiteren befinden sich die Parameter dessen: {| class="wikitable" ! Nummer || Befehl || Beschreibung |- | 0 || NOP || Keine Operation, dieser Code wird bei den Antworten für den Status des Tasters verwendet |- | 1 || Restart || Neustart des Mikrocontrollers (ersetzt das Aus- und Einstecken nachdem der Modus umgestellt wurde) |- | 2 || Lesen Modus || Gibt den Interface-Modus zurück |- | 3 || Setzen Modus || Setzt den Interface-Modus |- | 4 || Lesen Einzeltaste || Gibt den Keycode der Einzeltasten-Tastatur zurück |- | 5 || Setzen Einzeltaste || Setzt den Keycode der Einzeltasten-Tastatur |- | 6 || Lesen Tastensequenz || Gibt 6 Byte der Sequenz des angegebenen Blocks (in Byte 1) zurück |- | 7 || Setzen Tastensequenz || Setzt die 6 Bytes der Sequenz des angegebenen Blocks (in Byte 1) |} Jeder Befehl wird beantwortet, wobei dem ersten Byte eine Statusinformation mit bitweise Oder hinzugefügt wird: {| class="wikitable" ! Nummer || Status || Beschreibung |- | 0x00 || None || Wird nicht verwendet |- | 0x40 || Busy || Der Befehl wurde nicht ausgeführt, weil der Controller beschäftigt ist |- | 0x80 || Ok || Der Befehl wurde erfolgreich ausgeführt, die optionale Antwort befindet sich in den restlichen Bytes |- | 0xC0 || Error || Beim Ausführen des Befehls ist ein Fehler aufgetreten |} ===Tastenstatus=== Für jede Änderung des Tastenstatus wird ein Report übertragen: <code>&lt; <span class="hb1">00</span> <span class="hb2">BB</span> xx xx xx xx xx xx</code> * <span class="hb1">"Befehl": Status der Taste</span> * <span class="hb2">Status der Taste - 0: nicht gedrückt, 1: gedrückt</span> ==Modus 1: Einzeltasten-Tastatur== In diesem Modus verhält sich der Fußtaster wie die Taste einer Tastatur. Die zu drückende Taste kann über Modus 2 festgelegt werden. Leider ist es aktuell noch nicht möglich, Multimedia-Tasten (Wiedergabesteuerung, Lautstärke, Anwendungssteuerung) zu verwenden. ===Lesen=== Zum Zurücklesen der verwendeten Taste muss folgender Report gesendet werden: <code>&gt; <span class="hb1">04</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste</span> Die Antwort entspricht folgendem Muster: <code>&lt; <span class="hb1">84</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste (OK)</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) ** 0x01: Steuerung links ** 0x02: Umschalttaste links ** 0x04: Alt links ** 0x08: GUI links (u. a. Windows-Taste) ** 0x10: Steuerung rechts ** 0x20: Umschalttaste rechts ** 0x40: Alt rechts (müsste Alt+Gr sein) ** 0x80: GUI rechts (müsste Kontextmenü sein) * <span class="hb3">Keycode Taste</span> ===Schreiben=== Zum Setzen einer Taste folgender Report gesendet werden: <code>&gt; <span class="hb1">05</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Setzen Einzeltaste</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) * <span class="hb3">Keycode Taste</span> Die restlichen Bytes im Report werden ignoriert. Die Bestätigung wird wie unter "Modus 2" beschrieben gesendet. Da keine Readback stattfindet, wird immer mit "OK" geantwortet: <code>&lt; <span class="hb1">85</span> xx xx xx xx xx xx xx</code> ==Modus 2: Makro-Tastatur== Über die Makro-Tastatur können längere Tastenfolgen ausgegeben werden. Für diesen Zweck sind 128 Byte im EEPROM vorgesehen, was einer maximalen Folge von etwa 63 Anschlägen entspricht. Aktuell kann nur eine Taste gleichzeitig gedrückt werden kann - ein Rollover ist dementsprechend nicht möglich. Die Ausgabe erfolgt mit maximaler Geschwindigkeit, also mit etwa 100 Anschlägen pro Sekunde, wobei zwischen gleichlautenden Anschlägen sowie nach dem letzten Zeichen automatisch ein Loslassen der Taste eingefügt wird, was zu einer kleinen Verzögerung führt und damit das Timing verändert Beispiel: Bei der Ausgabe des Wortes <code>Hallo</code> folgende Reports übertragen: * Umschalttaste drücken, Taste "H" drücken * Umschalttaste loslassen, Taste "A" drücken * Taste "L" drücken * Taste "L" loslassen * Taste "L" drücken * Taste "O" drücken * Taste "O" loslassen So dauert die Übertragung des Wortes - bei einem Report-Intervall von 10 ms - etwa 70 ms statt den zunächst anzunehmenden 50 ms. ===Datenformat=== Die Daten werden im Muster <code>Befehl + Daten</code> gespeichert, wobei die Datenlänge dynamisch (aber anhand des Befehls ersichtlich) ist. Dementsprechend sind die Befehle teilweise als Flags aufgebaut, zum besseren Verständnis hier im Binärformat: * <code>0b<b>11111111</b></code>: Ende der Sequenz (entspricht nicht beschriebenen Speicherzellen), keine Daten * <code>0b<b>1</b><span class="hb1">ppppppp</span></code>: Pause in 5 ms-Schritten, p = 0 ... 126, t = (p + 1) * 5 ms, maximal 635 ms, keine Daten * <code>0b<b>0</b><span class="hb2">mm</span><span class="hb3">xx</span>xxx</code>: Verhalten der Modifier ** <code><span class="hb2">0b00</span></code>: Modifier beibehalten, keine Daten ** <code><span class="hb2">0b01</span></code>: Modifier für nachfolgende Taste drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb2">0b10</span></code>: Modifier dauerhaft halten, +1 Byte Daten ** <code><span class="hb2">0b11</span></code>: Modifier loslassen, keine Daten * <code>0b<b>0</b><span class="hb2">xx</span><span class="hb3">kk</span>xxx</code>: Verhalten der Taste ** <code><span class="hb3">0b00</span></code>: Taste beibehalten, keine Daten ** <code><span class="hb3">0b01</span></code>: Taste einmal drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb3">0b10</span></code>: Taste dauerhaft halten (bis eine andere Taste gedrückt wird), +1 Byte Daten ** <code><span class="hb3">0b11</span></code>: Taste loslassen, keine Daten Sollen Modifier und Taste mit einem Befehl verändert werden, wird zuerst der Modifier erwartet, dann die Taste: <code>0b0<span class="hb2">10</span><span class="hb3">01</span>000 <span class="hb4">0b00000010</span> <span class="hb5">0b00001011</span> <span class="hb2">Drückt und hält</span> die <span class="hb4">linke Umschalttaste</span> und drückt die <span class="hb5">Taste H (0x0B)</span> <span class="hb3">einmal</span>. Beispiel: Es soll die Zeichenfolge <code>Hallo WELT</code> mit anschließendem Zeilenumbruch ausgegeben werden, mit einer Pause von 500 ms nach "Hallo". Die Sequenz sieht nun wie folgt aus (Binär und Hex gemischt, Hex für Keycodes): {| class="wikitable" ! Code || Befehl || Parameter |- | <code>0b0<span class="hb1">01</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x0B</span></code> || <span class="hb1">Modifier einmal drücken</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Linke Umschalttaste</span>, <span class="hb4">Taste H</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x04</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste A</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x12</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste O</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1100011</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Pause mit 99 Zeiteinheiten</span>: t = (99 + 1) * 5 ms = 500 ms |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb3">0x2C</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Leertaste</span> |- | <code>0b0<span class="hb1">11</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x1A</span></code> || <span class="hb1">Modifier drücken und halten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Rechte Umschalttaste</span>, <span class="hb4">Taste W</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x08</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste E</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x17</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste T</span> |- | <code>0b0<span class="hb1">10</span><span class="hb2">00</span>000</code> || <span class="hb1">Modifier loslassen</span>, <span class="hb2">Kein Tastendruck</span> || - |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x28</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Return-Taste</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1111111</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Ende der der Sequenz</span> |} ===Lesen=== Wie bereits in der Befehlsübersicht erwähnt, erfolgt das Lesen und Schreiben der Sequenzdaten in Blöcken: <code>&gt; <span class="hb1">06</span> <span class="hb2">CC</span> xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> Als Antwort bekommt man dann die Daten des jeweiligen Blocks: <code>&lt; <span class="hb1">86</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Lesen Sequenz (OK)</span> * <span class="hb2">Blocknummer: 0 ... 21 </span> * <span class="hb2">6 Datenbytes des Blocks</span> Ist der letzte Block nicht "füllend", sind die restlichen Bytes zufällig, ebenso kann über das "End of Sequence" hinaus gelesen werden. ===Schreiben=== Das Schreiben von Blöcken ist der Antwort vom Lesen sehr ähnlich: <code>&gt; <span class="hb1">07</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Schreiben Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> * <span class="hb2">6 Datenbytes des Blocks</span> Sobald die Daten geschrieben wurden, antwortet der Mikrocontroller mit: <code>&lt; <span class="hb1">06</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Schreiben Sequenz (OK)</span> ==Modus 3: Gamepad== Es ist keine Konfiguration notwendig, das Gamepad meldet sich mit einer Taste und kann in Anwendungen wie gewohnt zugeordnet werden. <gallery> footswitch_gamepad.png|Eigenschaftenseite in Windows </gallery> Leider erkennt weder Firefox 73 noch Chromium 82 das Pad im html5gamepad-Tester. Anzumerken ist, dass wie bei der Einzeltasten-Tastatur Reports nur bei Zustandsänderung der Taste gesendet werden. Bis jetzt konnte ich dadurch keine Einschränkungen feststellen. =PC-Software= Aktuell gibt es eine kleine Python-Lib und ein paar Beispiele dazu. Siehe Downloads. =Anmerkungen= * Die Firmware auf dem Tiny85 zu entwickeln war grauenvoll, da man nur sehr schlecht debuggen kann. Das nächste Mal lieber auf einem Mikrocontroller mit deutlich mehr IOs und Hardware-UART entwickeln und anschließend auf ein kleineres Geschwister portieren * [https://github.com/micronucleus/micronucleus/ micronucleus] ist ein USB-Bootloader basierend auf V-USB, den ich bis jetzt noch nicht verwendet habe, in Zukunft aber sollte * Der Quellcode steht, wie von objective development gefordert, unter GPLv2 =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= * [[Datei:Footswitch.zip]] Schaltplan & Layout in EAGLE 7.7.0, Firmware & Sourcen in Atmel Studio 7, Beispielanwendung in Python 3.7 =Weblinks= * [https://www.uwe-sieber.de/usbtreeview.html USB Device Tree Viewer] zeigt sehr detaillierte Infos zu angeschlossenen USB-Geräten an * [http://wireshark.org/ Wireshark] kann auch USB tracen * [https://eleccelerator.com/usbdescreqparser/ USB Descriptor and Request Parser] * [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 Universal Serial Bus HID Usage Tables, Seite 53: 10 Keyboard/Keypad Page (0x07)] [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:Kleine Helferlein]] 433bedd097be99293469919a4c6cf43e998dd3cf 1429 1428 2020-03-01T17:41:46Z Qsysopr 1 Qsysopr verschob die Seite [[Fußtaster]] nach [[USB-Fußtaster]], ohne dabei eine Weiterleitung anzulegen: Blöder Titel wikitext text/x-wiki [[Datei:Footswitch.jpg|thumb|Fertig aufgebauter Fußtaster]] "Schau Mama, freihändig!" Wer kennt das nicht? Man muss auf mehreren Leiterkarten verschiedene Spannungen messen. Üblicherweise läuft es dann wie folgt ab: # Messspitzen platzieren # Wert vom Messgerät ablesen # Messspitzen ablegen und zum PC umdrehen # Messwert eintippen # Zurückdrehen, Messspitzen wieder in die Hände nehmen # Nochmal nachschauen, welcher Messpunkt jetzt dran ist # Wiederholen Ab und zu mischt sich dann das erneute Messen ein, weil ein Wert unplausibel ist und man entweder einen Zahlendreher drin oder schneller getippt als gedacht hat. Unterm Strich ist es auf jeden Fall sehr zeitraubend und nervig. Gleichzeitig baumeln die Füße unbeteiligt am Stuhl herunter. Die meisten Messgeräte (und anderes Laborequipment) lassen sich über den PC kontrollieren, warum also nicht gleich die richtigen Werte z. B. nach Excel transferieren? Nur irgendwie muss man den Prozess anstoßen... =Die schnelle Lösung= Tastatur ist blöd, also muss eine andere Eingabemöglichkeit her. Ein Taster und eine Projektbox ist schnell gefunden, Loch in die Box und ein paar große Schrauben dazu (damit sie nicht gleich abhaut) und fertig ist der improvisierte Fußtaster. Nur wie kommt die Info in den PC? Die serielle Schnittstelle hat neben Rx und Tx oft auch Steuerleitungen – aus den alten Tagen, in denen Modems noch so richtig langsam waren. Diese lassen sich in so ziemlich jeder Programmiersprache kontrollieren und abfragen. Ein FT232 liegt auch noch herum, also Taster angelötet und los geht’s! Das Programm ist in Python geschrieben, pollt die CTS-Leitung und sobald diese low wird, wird per pyVisa den Multimeter der aktuelle Messwert entlockt, passend formatiert und mit dem Keyboard-Modul "ausgetippt". Damit die Augen am Mikroskop bleiben können, wird zudem ein kurzer Piepton ausgegeben. Sehr viel Spaß für wenig Geld. Leider muss man bei jeder Benutzung schauen, welcher COM-Port dem Adapter zugeordnet wurde und ob dieser auch wirklich im Script steht. =Die schöne Lösung= Eines Tages brachte mein Kollege einen kleinen Pappkarton vom [https://www.pollin.de Ramschmax] mit, Inhalt: [https://www.pollin.de/p/fusstaster-pfs-135a-10-a-250-v-420705 420705]. Ein Gusseiserner Fußtaster mit schönem Klick-Klack-Mikroschalter. Der hat etwas besseres als den schnöden UART-Adapter mit Zwillingslitze verdient – endlich wieder eine schöne Anwendung für [https://www.obdev.at/vusb/ V-USB]! Was soll das Teil können? Am besten natürlich so viel wie möglich, damit es vielleicht sogar als "Adaptive Controller" dienen kann. Deshalb habe ich mich dafür entschieden, einen Multidevice-Ansatz zu fahren. Das umfasst aktuell: * Generisches USB-HID * Einzeltasten-Tastatur * Makro-Tastatur * Joystick =Hardware= Die Hardware könnte nicht einfacher sein - sie entspricht größtenteils dem [https://www.obdev.at/products/vusb/easylogger.html Easylogger]-Beispielprojekt, nur dass anstelle der automatischen Oszillator-Kalibrierung ein externer Quarz verwendet wird. Hintergrund hierfür ist, dass das [[SNES-Joypad]], das sich selbst kalibriert (oder zumindest sollte), am RetroPie beim Booten oft nicht erkannt wird. Kann aber auch gut sein, dass es sich um einen Bug in meiner Firmware handelt. Die Bauteile sind - abgesehen vom Quarz und Mikrocontroller in SMD-Bauform. Als MCU werkelt fürs Erste ein ATtiny85, der später noch herunterskaliert werden kann. Die Wahl auf das DIP-Gehäuse fiel, um ohne Löten die Firmware herunterzuladen. Mit Quarz als Taktquelle bleibt noch ein "richtiger" IO übrig (sofern man den Reset-Pin nicht deaktiviert) - mehr braucht man nicht. Eine eigens designte Leiterkarte ist aufgrund der Einfachheit der Schaltung völlig unnötig, aber es war noch Platz auf dem Panel... <gallery> footswitch 1.0 sch.png|Schaltplan footswitch 1.0 top.png|Bestückungsplan Oberseite footswitch 1.0 bot.png|Bestückungsplan Unterseite footswitch 1.0 assy.jpg|Aufgebaute Leiterkarte </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || MA03-1 || |- | 1 || SV1 || || MA04-1 || GC 2212-EU030 |- | 1 || C1 || 100n || C0603 || X7R-G0603 100N |- | 1 || C4 || 10u || C0805 || KEM X7R0805 10U |- | 1 || Q1 || 12M || HC49U-V || 12,0000-HC49U-S |- | 1 || R11 || 150 || R0603 || RND 0603 1 150 |- | 1 || C5 || 150n || C0603 || X7R 0603FCE 150N |- | 2 || C2, C3 || 22p || C0603 || RND 150MT18N2202 |- | 1 || R3 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || R10 || 4k7 || R0603 || RND 0603 1 4,7k |- | 2 || R1, R2 || 68 || R0603 || RND 0603 1 68 |- | 1 || IC1 || ATTINY 85-20 PU || DIL08 || ATTINY 85-20 PU |- | 2 || D1, D2 || BZX84C3V6 || SOT23 || SMD ZD 3,6 |} Leider stellte sich erst zu spät heraus, dass die Leiterkarte ein bisschen zu groß ist, um sie an der eigentlich vorgesehenen Stelle zu montieren. Man kann sie zwar ein bisschen schräg anschrauben und von der Ecke noch etwas Material wegnehmen, aber dann ist die USB-Leitung auch wieder im Weg. Das Design ist also nicht so richtig geglückt... Aber kein Problem, dass man nicht mit ein bisschen Schrumpfschlauch lösen könnte: <gallery> footswitch 1.0 designflaw 1.jpg|Dort sollte die Leiterkarte hin footswitch 1.0 designflaw 2.jpg|...und hier ist sie footswitch 1.0 designflaw 3.jpg|weitere Perspektive </gallery> Der Schirm ist übrigens auf ein Stück Leitung gecrimpt, das wiederum an die Halterung des Tasters gelötet ist. =Firmware= ==Firmware== {{Infobox AVR | Typ = ATtiny85 | Takt = 12 | FuseH = D7 | FuseL = DE | FuseE = FF }} Die Firmware ist mehr oder weniger viergeteilt, entsprechend den verschiedenen Modi. Hierfür gibt es mehrere Gründe: * die freien VID/PID-Paare sind auf die verschiedenen Funktionen beschränkt und es lässt sich nicht zweifelsfrei sagen, ob Multi-Endpoint-Konfigurationen erlaubt sind * Die Fragmentierung macht den Code (teilweise) einfacher und übersichtlicher * Keinerlei Treiberprobleme (es gibt wohl Betriebssysteme, die sich an Multi-Endpoint verschlucken) * Es ist nicht ganz so üblich und in der Implementierung interessanter Nach dem Reset liest die Firmware den zu verwendenden Modus aus dem EEPROM. Ist diese ungültig oder der IO des Tasters auf Masse gezogen, wird der auf Generisches HID gesetzt. Gegenüber des USB-Treibers wird nun auch der Pointer für die USB-Deskriptoren gesetzt (die sich wiederum im Flash befinden). Anschließend läuft die Initialisierung der unterschiedlichen Modi und es wird in die entsprechende Endlosschleife gesprungen. Als USB VID/PID-Paare werden von obdev frei zur Verfügung gestellten verwendet: * HID: 0x16C0/0x27D9 * Tastatur: 0x16C0/0x27DB * Gamepad: 0x16C0/0x27DC Im Grunde ist das alles kein Hexenwerk, allerdings haben die "Dynamisierung" der USB-Deskriptoren einiges an (auf dem Attiny schwierige) Fehlersuche gekostet. Über Manche Dinge, wie z. B. wie man die verschiedenen Deskriptoren den Anfragen zuordnet, ist die Dokumentation leider etwas vage (oder ich habe sie nicht richtig gelesen/falsch gesucht). Auch lässt sich die Firmware noch ziemlich optimieren, das gesteckte Ziel wäre, dass sie auf den ATtiny45 passt. Aktuell ist hauptsächlich die RAM-Belegung ein Problem (und noch nicht optimal). =Konfiguration= Um die Konfiguration des Fußtasters ändern zu können, muss er sich in Modus 2 (Generisches HID) befinden. Sollte dieser Modus nicht aktiv sein, kann er erreicht werden indem der Taster gedrückt wird, während der USB-Stecker verbunden wird. In den Report-Besispielen werden stats hexadezimale Zahlen verwendet. Angaben mit <code>xx</code> sind beliebig bzw. müssen ignoriert werden. ==Keycodes== Bevor auf die verschiedenen Funktionen im Detail eingegangen wird, ein paar Worte zu den Keycodes: Tastaturen sind seit jeher ziemlich einfach gestrickt. So "weiß" der Controller der Tastatur zwar an welcher Position eine Taste gedrückt wird, aber nicht welches Layout sie vertritt - dies wird erst durch das Betriebssystem umgestzt. Das hat zum Beispiel den Effekt, dass mit einer deutschen Tastatur an einem auf englisch eingestellten PC u. a. Y und Z vertauscht sind (und man beim Raspberrz Pi das Passwort mindestens einmal falsch eingibt). Diese Eigenschaft betrifft natürlich auch den Fußtaster. Die Keycodes für englische Tastaturen können in der Spezifikation [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 "Universal Serial Bus HID Usage Tables"] in der aktuellen Version ab Seite 53 (Kapitel 10 Keyboard/Keypad Page (0x07)]) nachgeschlagen werden. Für das deutsche Layout befindet sich eine Tabelle im Download-Bereich (keine Garantie auf Vollständigkeit und Korrektheit). ==Modus 0: Generisches HID== Die Kommunikation findet über Report ID 0 mit 8 Datenbytes statt. Beim Senden von Reports definiert das erste Byte den Befehl, in den weiteren befinden sich die Parameter dessen: {| class="wikitable" ! Nummer || Befehl || Beschreibung |- | 0 || NOP || Keine Operation, dieser Code wird bei den Antworten für den Status des Tasters verwendet |- | 1 || Restart || Neustart des Mikrocontrollers (ersetzt das Aus- und Einstecken nachdem der Modus umgestellt wurde) |- | 2 || Lesen Modus || Gibt den Interface-Modus zurück |- | 3 || Setzen Modus || Setzt den Interface-Modus |- | 4 || Lesen Einzeltaste || Gibt den Keycode der Einzeltasten-Tastatur zurück |- | 5 || Setzen Einzeltaste || Setzt den Keycode der Einzeltasten-Tastatur |- | 6 || Lesen Tastensequenz || Gibt 6 Byte der Sequenz des angegebenen Blocks (in Byte 1) zurück |- | 7 || Setzen Tastensequenz || Setzt die 6 Bytes der Sequenz des angegebenen Blocks (in Byte 1) |} Jeder Befehl wird beantwortet, wobei dem ersten Byte eine Statusinformation mit bitweise Oder hinzugefügt wird: {| class="wikitable" ! Nummer || Status || Beschreibung |- | 0x00 || None || Wird nicht verwendet |- | 0x40 || Busy || Der Befehl wurde nicht ausgeführt, weil der Controller beschäftigt ist |- | 0x80 || Ok || Der Befehl wurde erfolgreich ausgeführt, die optionale Antwort befindet sich in den restlichen Bytes |- | 0xC0 || Error || Beim Ausführen des Befehls ist ein Fehler aufgetreten |} ===Tastenstatus=== Für jede Änderung des Tastenstatus wird ein Report übertragen: <code>&lt; <span class="hb1">00</span> <span class="hb2">BB</span> xx xx xx xx xx xx</code> * <span class="hb1">"Befehl": Status der Taste</span> * <span class="hb2">Status der Taste - 0: nicht gedrückt, 1: gedrückt</span> ==Modus 1: Einzeltasten-Tastatur== In diesem Modus verhält sich der Fußtaster wie die Taste einer Tastatur. Die zu drückende Taste kann über Modus 2 festgelegt werden. Leider ist es aktuell noch nicht möglich, Multimedia-Tasten (Wiedergabesteuerung, Lautstärke, Anwendungssteuerung) zu verwenden. ===Lesen=== Zum Zurücklesen der verwendeten Taste muss folgender Report gesendet werden: <code>&gt; <span class="hb1">04</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste</span> Die Antwort entspricht folgendem Muster: <code>&lt; <span class="hb1">84</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste (OK)</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) ** 0x01: Steuerung links ** 0x02: Umschalttaste links ** 0x04: Alt links ** 0x08: GUI links (u. a. Windows-Taste) ** 0x10: Steuerung rechts ** 0x20: Umschalttaste rechts ** 0x40: Alt rechts (müsste Alt+Gr sein) ** 0x80: GUI rechts (müsste Kontextmenü sein) * <span class="hb3">Keycode Taste</span> ===Schreiben=== Zum Setzen einer Taste folgender Report gesendet werden: <code>&gt; <span class="hb1">05</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Setzen Einzeltaste</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) * <span class="hb3">Keycode Taste</span> Die restlichen Bytes im Report werden ignoriert. Die Bestätigung wird wie unter "Modus 2" beschrieben gesendet. Da keine Readback stattfindet, wird immer mit "OK" geantwortet: <code>&lt; <span class="hb1">85</span> xx xx xx xx xx xx xx</code> ==Modus 2: Makro-Tastatur== Über die Makro-Tastatur können längere Tastenfolgen ausgegeben werden. Für diesen Zweck sind 128 Byte im EEPROM vorgesehen, was einer maximalen Folge von etwa 63 Anschlägen entspricht. Aktuell kann nur eine Taste gleichzeitig gedrückt werden kann - ein Rollover ist dementsprechend nicht möglich. Die Ausgabe erfolgt mit maximaler Geschwindigkeit, also mit etwa 100 Anschlägen pro Sekunde, wobei zwischen gleichlautenden Anschlägen sowie nach dem letzten Zeichen automatisch ein Loslassen der Taste eingefügt wird, was zu einer kleinen Verzögerung führt und damit das Timing verändert Beispiel: Bei der Ausgabe des Wortes <code>Hallo</code> folgende Reports übertragen: * Umschalttaste drücken, Taste "H" drücken * Umschalttaste loslassen, Taste "A" drücken * Taste "L" drücken * Taste "L" loslassen * Taste "L" drücken * Taste "O" drücken * Taste "O" loslassen So dauert die Übertragung des Wortes - bei einem Report-Intervall von 10 ms - etwa 70 ms statt den zunächst anzunehmenden 50 ms. ===Datenformat=== Die Daten werden im Muster <code>Befehl + Daten</code> gespeichert, wobei die Datenlänge dynamisch (aber anhand des Befehls ersichtlich) ist. Dementsprechend sind die Befehle teilweise als Flags aufgebaut, zum besseren Verständnis hier im Binärformat: * <code>0b<b>11111111</b></code>: Ende der Sequenz (entspricht nicht beschriebenen Speicherzellen), keine Daten * <code>0b<b>1</b><span class="hb1">ppppppp</span></code>: Pause in 5 ms-Schritten, p = 0 ... 126, t = (p + 1) * 5 ms, maximal 635 ms, keine Daten * <code>0b<b>0</b><span class="hb2">mm</span><span class="hb3">xx</span>xxx</code>: Verhalten der Modifier ** <code><span class="hb2">0b00</span></code>: Modifier beibehalten, keine Daten ** <code><span class="hb2">0b01</span></code>: Modifier für nachfolgende Taste drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb2">0b10</span></code>: Modifier dauerhaft halten, +1 Byte Daten ** <code><span class="hb2">0b11</span></code>: Modifier loslassen, keine Daten * <code>0b<b>0</b><span class="hb2">xx</span><span class="hb3">kk</span>xxx</code>: Verhalten der Taste ** <code><span class="hb3">0b00</span></code>: Taste beibehalten, keine Daten ** <code><span class="hb3">0b01</span></code>: Taste einmal drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb3">0b10</span></code>: Taste dauerhaft halten (bis eine andere Taste gedrückt wird), +1 Byte Daten ** <code><span class="hb3">0b11</span></code>: Taste loslassen, keine Daten Sollen Modifier und Taste mit einem Befehl verändert werden, wird zuerst der Modifier erwartet, dann die Taste: <code>0b0<span class="hb2">10</span><span class="hb3">01</span>000 <span class="hb4">0b00000010</span> <span class="hb5">0b00001011</span> <span class="hb2">Drückt und hält</span> die <span class="hb4">linke Umschalttaste</span> und drückt die <span class="hb5">Taste H (0x0B)</span> <span class="hb3">einmal</span>. Beispiel: Es soll die Zeichenfolge <code>Hallo WELT</code> mit anschließendem Zeilenumbruch ausgegeben werden, mit einer Pause von 500 ms nach "Hallo". Die Sequenz sieht nun wie folgt aus (Binär und Hex gemischt, Hex für Keycodes): {| class="wikitable" ! Code || Befehl || Parameter |- | <code>0b0<span class="hb1">01</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x0B</span></code> || <span class="hb1">Modifier einmal drücken</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Linke Umschalttaste</span>, <span class="hb4">Taste H</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x04</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste A</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x12</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste O</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1100011</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Pause mit 99 Zeiteinheiten</span>: t = (99 + 1) * 5 ms = 500 ms |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb3">0x2C</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Leertaste</span> |- | <code>0b0<span class="hb1">11</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x1A</span></code> || <span class="hb1">Modifier drücken und halten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Rechte Umschalttaste</span>, <span class="hb4">Taste W</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x08</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste E</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x17</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste T</span> |- | <code>0b0<span class="hb1">10</span><span class="hb2">00</span>000</code> || <span class="hb1">Modifier loslassen</span>, <span class="hb2">Kein Tastendruck</span> || - |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x28</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Return-Taste</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1111111</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Ende der der Sequenz</span> |} ===Lesen=== Wie bereits in der Befehlsübersicht erwähnt, erfolgt das Lesen und Schreiben der Sequenzdaten in Blöcken: <code>&gt; <span class="hb1">06</span> <span class="hb2">CC</span> xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> Als Antwort bekommt man dann die Daten des jeweiligen Blocks: <code>&lt; <span class="hb1">86</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Lesen Sequenz (OK)</span> * <span class="hb2">Blocknummer: 0 ... 21 </span> * <span class="hb2">6 Datenbytes des Blocks</span> Ist der letzte Block nicht "füllend", sind die restlichen Bytes zufällig, ebenso kann über das "End of Sequence" hinaus gelesen werden. ===Schreiben=== Das Schreiben von Blöcken ist der Antwort vom Lesen sehr ähnlich: <code>&gt; <span class="hb1">07</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Schreiben Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> * <span class="hb2">6 Datenbytes des Blocks</span> Sobald die Daten geschrieben wurden, antwortet der Mikrocontroller mit: <code>&lt; <span class="hb1">06</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Schreiben Sequenz (OK)</span> ==Modus 3: Gamepad== Es ist keine Konfiguration notwendig, das Gamepad meldet sich mit einer Taste und kann in Anwendungen wie gewohnt zugeordnet werden. <gallery> footswitch_gamepad.png|Eigenschaftenseite in Windows </gallery> Leider erkennt weder Firefox 73 noch Chromium 82 das Pad im html5gamepad-Tester. Anzumerken ist, dass wie bei der Einzeltasten-Tastatur Reports nur bei Zustandsänderung der Taste gesendet werden. Bis jetzt konnte ich dadurch keine Einschränkungen feststellen. =PC-Software= Aktuell gibt es eine kleine Python-Lib und ein paar Beispiele dazu. Siehe Downloads. =Anmerkungen= * Die Firmware auf dem Tiny85 zu entwickeln war grauenvoll, da man nur sehr schlecht debuggen kann. Das nächste Mal lieber auf einem Mikrocontroller mit deutlich mehr IOs und Hardware-UART entwickeln und anschließend auf ein kleineres Geschwister portieren * [https://github.com/micronucleus/micronucleus/ micronucleus] ist ein USB-Bootloader basierend auf V-USB, den ich bis jetzt noch nicht verwendet habe, in Zukunft aber sollte * Der Quellcode steht, wie von objective development gefordert, unter GPLv2 =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= * [[Datei:Footswitch.zip]] Schaltplan & Layout in EAGLE 7.7.0, Firmware & Sourcen in Atmel Studio 7, Beispielanwendung in Python 3.7 =Weblinks= * [https://www.uwe-sieber.de/usbtreeview.html USB Device Tree Viewer] zeigt sehr detaillierte Infos zu angeschlossenen USB-Geräten an * [http://wireshark.org/ Wireshark] kann auch USB tracen * [https://eleccelerator.com/usbdescreqparser/ USB Descriptor and Request Parser] * [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 Universal Serial Bus HID Usage Tables, Seite 53: 10 Keyboard/Keypad Page (0x07)] [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:Kleine Helferlein]] 433bedd097be99293469919a4c6cf43e998dd3cf 1431 1429 2020-03-01T17:45:05Z Qsysopr 1 Tippfehler korrigiert wikitext text/x-wiki [[Datei:Footswitch.jpg|thumb|Fertig aufgebauter Fußtaster]] "Schau Mama, freihändig!" Wer kennt das nicht? Man muss auf mehreren Leiterkarten verschiedene Spannungen messen. Üblicherweise läuft es dann wie folgt ab: # Messspitzen platzieren # Wert vom Messgerät ablesen # Messspitzen ablegen und zum PC umdrehen # Messwert eintippen # Zurückdrehen, Messspitzen wieder in die Hände nehmen # Nochmal nachschauen, welcher Messpunkt jetzt dran ist # Wiederholen Ab und zu mischt sich dann das erneute Messen ein, weil ein Wert unplausibel ist und man entweder einen Zahlendreher drin oder schneller getippt als gedacht hat. Unterm Strich ist es auf jeden Fall sehr zeitraubend und nervig. Gleichzeitig baumeln die Füße unbeteiligt am Stuhl herunter. Die meisten Messgeräte (und anderes Laborequipment) lassen sich über den PC kontrollieren, warum also nicht gleich die richtigen Werte z. B. nach Excel transferieren? Nur irgendwie muss man den Prozess anstoßen... =Die schnelle Lösung= Tastatur ist blöd, also muss eine andere Eingabemöglichkeit her. Ein Taster und eine Projektbox ist schnell gefunden, Loch in die Box und ein paar große Schrauben dazu (damit sie nicht gleich abhaut) und fertig ist der improvisierte Fußtaster. Nur wie kommt die Info in den PC? Die serielle Schnittstelle hat neben Rx und Tx oft auch Steuerleitungen – aus den alten Tagen, in denen Modems noch so richtig langsam waren. Diese lassen sich in so ziemlich jeder Programmiersprache kontrollieren und abfragen. Ein FT232 liegt auch noch herum, also Taster angelötet und los geht’s! Das Programm ist in Python geschrieben, pollt die CTS-Leitung und sobald diese low wird, wird per pyVisa den Multimeter der aktuelle Messwert entlockt, passend formatiert und mit dem Keyboard-Modul "ausgetippt". Damit die Augen am Mikroskop bleiben können, wird zudem ein kurzer Piepton ausgegeben. Sehr viel Spaß für wenig Geld. Leider muss man bei jeder Benutzung schauen, welcher COM-Port dem Adapter zugeordnet wurde und ob dieser auch wirklich im Script steht. =Die schöne Lösung= Eines Tages brachte mein Kollege einen kleinen Pappkarton vom [https://www.pollin.de Ramschmax] mit, Inhalt: [https://www.pollin.de/p/fusstaster-pfs-135a-10-a-250-v-420705 420705]. Ein Gusseiserner Fußtaster mit schönem Klick-Klack-Mikroschalter. Der hat etwas Besseres als den schnöden UART-Adapter mit Zwillingslitze verdient – endlich wieder eine schöne Anwendung für [https://www.obdev.at/vusb/ V-USB]! Was soll das Teil können? Am besten natürlich so viel wie möglich, damit es vielleicht sogar als "Adaptive Controller" dienen kann. Deshalb habe ich mich dafür entschieden, einen Multidevice-Ansatz zu fahren. Das umfasst aktuell: * Generisches USB-HID * Einzeltasten-Tastatur * Makro-Tastatur * Joystick =Hardware= Die Hardware könnte nicht einfacher sein - sie entspricht größtenteils dem [https://www.obdev.at/products/vusb/easylogger.html Easylogger]-Beispielprojekt, nur dass anstelle der automatischen Oszillator-Kalibrierung ein externer Quarz verwendet wird. Hintergrund hierfür ist, dass das [[SNES-Joypad]], das sich selbst kalibriert (oder zumindest sollte), am RetroPie beim Booten oft nicht erkannt wird. Kann aber auch gut sein, dass es sich um einen Bug in meiner Firmware handelt. Die Bauteile sind - abgesehen vom Quarz und Mikrocontroller in SMD-Bauform. Als MCU werkelt fürs Erste ein ATtiny85, der später noch herunterskaliert werden kann. Die Wahl auf das DIP-Gehäuse fiel, um ohne Löten die Firmware herunterzuladen. Mit Quarz als Taktquelle bleibt noch ein "richtiger" IO übrig (sofern man den Reset-Pin nicht deaktiviert) - mehr braucht man nicht. Eine eigens designte Leiterkarte ist aufgrund der Einfachheit der Schaltung völlig unnötig, aber es war noch Platz auf dem Panel... <gallery> footswitch 1.0 sch.png|Schaltplan footswitch 1.0 top.png|Bestückungsplan Oberseite footswitch 1.0 bot.png|Bestückungsplan Unterseite footswitch 1.0 assy.jpg|Aufgebaute Leiterkarte </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || MA03-1 || |- | 1 || SV1 || || MA04-1 || GC 2212-EU030 |- | 1 || C1 || 100n || C0603 || X7R-G0603 100N |- | 1 || C4 || 10u || C0805 || KEM X7R0805 10U |- | 1 || Q1 || 12M || HC49U-V || 12,0000-HC49U-S |- | 1 || R11 || 150 || R0603 || RND 0603 1 150 |- | 1 || C5 || 150n || C0603 || X7R 0603FCE 150N |- | 2 || C2, C3 || 22p || C0603 || RND 150MT18N2202 |- | 1 || R3 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || R10 || 4k7 || R0603 || RND 0603 1 4,7k |- | 2 || R1, R2 || 68 || R0603 || RND 0603 1 68 |- | 1 || IC1 || ATTINY 85-20 PU || DIL08 || ATTINY 85-20 PU |- | 2 || D1, D2 || BZX84C3V6 || SOT23 || SMD ZD 3,6 |} Leider stellte sich erst zu spät heraus, dass die Leiterkarte ein bisschen zu groß ist, um sie an der eigentlich vorgesehenen Stelle zu montieren. Man kann sie zwar ein bisschen schräg anschrauben und von der Ecke noch etwas Material wegnehmen, aber dann ist die USB-Leitung auch wieder im Weg. Das Design ist also nicht so richtig geglückt... Aber kein Problem, dass man nicht mit ein bisschen Schrumpfschlauch lösen könnte: <gallery> footswitch 1.0 designflaw 1.jpg|Dort sollte die Leiterkarte hin footswitch 1.0 designflaw 2.jpg|...und hier ist sie footswitch 1.0 designflaw 3.jpg|weitere Perspektive </gallery> Der Schirm ist übrigens auf ein Stück Leitung gecrimpt, das wiederum an die Halterung des Tasters gelötet ist. =Firmware= ==Firmware== {{Infobox AVR | Typ = ATtiny85 | Takt = 12 | FuseH = D7 | FuseL = DE | FuseE = FF }} Die Firmware ist mehr oder weniger viergeteilt, entsprechend den verschiedenen Modi. Hierfür gibt es mehrere Gründe: * die freien VID/PID-Paare sind auf die verschiedenen Funktionen beschränkt und es lässt sich nicht zweifelsfrei sagen, ob Multi-Endpoint-Konfigurationen erlaubt sind * Die Fragmentierung macht den Code (teilweise) einfacher und übersichtlicher * Keinerlei Treiberprobleme (es gibt wohl Betriebssysteme, die sich an Multi-Endpoint verschlucken) * Es ist nicht ganz so üblich und in der Implementierung interessanter Nach dem Reset liest die Firmware den zu verwendenden Modus aus dem EEPROM. Ist diese ungültig oder der IO des Tasters auf Masse gezogen, wird der auf Generisches HID gesetzt. Gegenüber des USB-Treibers wird nun auch der Pointer für die USB-Deskriptoren gesetzt (die sich wiederum im Flash befinden). Anschließend läuft die Initialisierung der unterschiedlichen Modi und es wird in die entsprechende Endlosschleife gesprungen. Als USB VID/PID-Paare werden von obdev frei zur Verfügung gestellten verwendet: * HID: 0x16C0/0x27D9 * Tastatur: 0x16C0/0x27DB * Gamepad: 0x16C0/0x27DC Im Grunde ist das alles kein Hexenwerk, allerdings haben die "Dynamisierung" der USB-Deskriptoren einiges an (auf dem Attiny schwierige) Fehlersuche gekostet. Über Manche Dinge, wie z. B. wie man die verschiedenen Deskriptoren den Anfragen zuordnet, ist die Dokumentation leider etwas vage (oder ich habe sie nicht richtig gelesen/falsch gesucht). Auch lässt sich die Firmware noch ziemlich optimieren, das gesteckte Ziel wäre, dass sie auf den ATtiny45 passt. Aktuell ist hauptsächlich die RAM-Belegung ein Problem (und noch nicht optimal). =Konfiguration= Um die Konfiguration des Fußtasters ändern zu können, muss er sich in Modus 2 (Generisches HID) befinden. Sollte dieser Modus nicht aktiv sein, kann er erreicht werden indem der Taster gedrückt wird, während der USB-Stecker verbunden wird. In den Report-Beispielen werden stets hexadezimale Zahlen verwendet. Angaben mit <code>xx</code> sind beliebig bzw. müssen ignoriert werden. ==Keycodes== Bevor auf die verschiedenen Funktionen im Detail eingegangen wird, ein paar Worte zu den Keycodes: Tastaturen sind seit jeher ziemlich einfach gestrickt. So "weiß" der Controller der Tastatur zwar an welcher Position eine Taste gedrückt wird, aber nicht welches Layout sie vertritt - dies wird erst durch das Betriebssystem umgesetzt. Das hat zum Beispiel den Effekt, dass mit einer deutschen Tastatur an einem auf Englisch eingestellten PC u. a. Y und Z vertauscht sind (und man beim Raspberrz Pi das Passwort mindestens einmal falsch eingibt). Diese Eigenschaft betrifft natürlich auch den Fußtaster. Die Keycodes für englische Tastaturen können in der Spezifikation [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 "Universal Serial Bus HID Usage Tables"] in der aktuellen Version ab Seite 53 (Kapitel 10 Keyboard/Keypad Page (0x07)]) nachgeschlagen werden. Für das deutsche Layout befindet sich eine Tabelle im Download-Bereich (keine Garantie auf Vollständigkeit und Korrektheit). ==Modus 0: Generisches HID== Die Kommunikation findet über Report ID 0 mit 8 Datenbytes statt. Beim Senden von Reports definiert das erste Byte den Befehl, in den weiteren befinden sich die Parameter dessen: {| class="wikitable" ! Nummer || Befehl || Beschreibung |- | 0 || NOP || Keine Operation, dieser Code wird bei den Antworten für den Status des Tasters verwendet |- | 1 || Restart || Neustart des Mikrocontrollers (ersetzt das Aus- und Einstecken nachdem der Modus umgestellt wurde) |- | 2 || Lesen Modus || Gibt den Interface-Modus zurück |- | 3 || Setzen Modus || Setzt den Interface-Modus |- | 4 || Lesen Einzeltaste || Gibt den Keycode der Einzeltasten-Tastatur zurück |- | 5 || Setzen Einzeltaste || Setzt den Keycode der Einzeltasten-Tastatur |- | 6 || Lesen Tastensequenz || Gibt 6 Byte der Sequenz des angegebenen Blocks (in Byte 1) zurück |- | 7 || Setzen Tastensequenz || Setzt die 6 Bytes der Sequenz des angegebenen Blocks (in Byte 1) |} Jeder Befehl wird beantwortet, wobei dem ersten Byte eine Statusinformation mit bitweise Oder hinzugefügt wird: {| class="wikitable" ! Nummer || Status || Beschreibung |- | 0x00 || None || Wird nicht verwendet |- | 0x40 || Busy || Der Befehl wurde nicht ausgeführt, weil der Controller beschäftigt ist |- | 0x80 || Ok || Der Befehl wurde erfolgreich ausgeführt, die optionale Antwort befindet sich in den restlichen Bytes |- | 0xC0 || Error || Beim Ausführen des Befehls ist ein Fehler aufgetreten |} ===Tastenstatus=== Für jede Änderung des Tastenstatus wird ein Report übertragen: <code>&lt; <span class="hb1">00</span> <span class="hb2">BB</span> xx xx xx xx xx xx</code> * <span class="hb1">"Befehl": Status der Taste</span> * <span class="hb2">Status der Taste - 0: nicht gedrückt, 1: gedrückt</span> ==Modus 1: Einzeltasten-Tastatur== In diesem Modus verhält sich der Fußtaster wie die Taste einer Tastatur. Die zu drückende Taste kann über Modus 2 festgelegt werden. Leider ist es aktuell noch nicht möglich, Multimedia-Tasten (Wiedergabesteuerung, Lautstärke, Anwendungssteuerung) zu verwenden. ===Lesen=== Zum Zurücklesen der verwendeten Taste muss folgender Report gesendet werden: <code>&gt; <span class="hb1">04</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste</span> Die Antwort entspricht folgendem Muster: <code>&lt; <span class="hb1">84</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste (OK)</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) ** 0x01: Steuerung links ** 0x02: Umschalttaste links ** 0x04: Alt links ** 0x08: GUI links (u. a. Windows-Taste) ** 0x10: Steuerung rechts ** 0x20: Umschalttaste rechts ** 0x40: Alt rechts (müsste Alt+Gr sein) ** 0x80: GUI rechts (müsste Kontextmenü sein) * <span class="hb3">Keycode Taste</span> ===Schreiben=== Zum Setzen einer Taste folgender Report gesendet werden: <code>&gt; <span class="hb1">05</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Setzen Einzeltaste</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) * <span class="hb3">Keycode Taste</span> Die restlichen Bytes im Report werden ignoriert. Die Bestätigung wird wie unter "Modus 2" beschrieben gesendet. Da keine Readback stattfindet, wird immer mit "OK" geantwortet: <code>&lt; <span class="hb1">85</span> xx xx xx xx xx xx xx</code> ==Modus 2: Makro-Tastatur== Über die Makro-Tastatur können längere Tastenfolgen ausgegeben werden. Für diesen Zweck sind 128 Byte im EEPROM vorgesehen, was einer maximalen Folge von etwa 63 Anschlägen entspricht. Aktuell kann nur eine Taste gleichzeitig gedrückt werden kann - ein Rollover ist dementsprechend nicht möglich. Die Ausgabe erfolgt mit maximaler Geschwindigkeit, also mit etwa 100 Anschlägen pro Sekunde, wobei zwischen gleichlautenden Anschlägen sowie nach dem letzten Zeichen automatisch ein Loslassen der Taste eingefügt wird, was zu einer kleinen Verzögerung führt und damit das Timing verändert Beispiel: Bei der Ausgabe des Wortes <code>Hallo</code> folgende Reports übertragen: * Umschalttaste drücken, Taste "H" drücken * Umschalttaste loslassen, Taste "A" drücken * Taste "L" drücken * Taste "L" loslassen * Taste "L" drücken * Taste "O" drücken * Taste "O" loslassen So dauert die Übertragung des Wortes - bei einem Report-Intervall von 10 ms - etwa 70 ms statt den zunächst anzunehmenden 50 ms. ===Datenformat=== Die Daten werden im Muster <code>Befehl + Daten</code> gespeichert, wobei die Datenlänge dynamisch (aber anhand des Befehls ersichtlich) ist. Dementsprechend sind die Befehle teilweise als Flags aufgebaut, zum besseren Verständnis hier im Binärformat: * <code>0b<b>11111111</b></code>: Ende der Sequenz (entspricht nicht beschriebenen Speicherzellen), keine Daten * <code>0b<b>1</b><span class="hb1">ppppppp</span></code>: Pause in 5 ms-Schritten, p = 0 ... 126, t = (p + 1) * 5 ms, maximal 635 ms, keine Daten * <code>0b<b>0</b><span class="hb2">mm</span><span class="hb3">xx</span>xxx</code>: Verhalten der Modifier ** <code><span class="hb2">0b00</span></code>: Modifier beibehalten, keine Daten ** <code><span class="hb2">0b01</span></code>: Modifier für nachfolgende Taste drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb2">0b10</span></code>: Modifier dauerhaft halten, +1 Byte Daten ** <code><span class="hb2">0b11</span></code>: Modifier loslassen, keine Daten * <code>0b<b>0</b><span class="hb2">xx</span><span class="hb3">kk</span>xxx</code>: Verhalten der Taste ** <code><span class="hb3">0b00</span></code>: Taste beibehalten, keine Daten ** <code><span class="hb3">0b01</span></code>: Taste einmal drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb3">0b10</span></code>: Taste dauerhaft halten (bis eine andere Taste gedrückt wird), +1 Byte Daten ** <code><span class="hb3">0b11</span></code>: Taste loslassen, keine Daten Sollen Modifier und Taste mit einem Befehl verändert werden, wird zuerst der Modifier erwartet, dann die Taste: <code>0b0<span class="hb2">10</span><span class="hb3">01</span>000 <span class="hb4">0b00000010</span> <span class="hb5">0b00001011</span> <span class="hb2">Drückt und hält</span> die <span class="hb4">linke Umschalttaste</span> und drückt die <span class="hb5">Taste H (0x0B)</span> <span class="hb3">einmal</span>. Beispiel: Es soll die Zeichenfolge <code>Hallo WELT</code> mit anschließendem Zeilenumbruch ausgegeben werden, mit einer Pause von 500 ms nach "Hallo". Die Sequenz sieht nun wie folgt aus (Binär und Hex gemischt, Hex für Keycodes): {| class="wikitable" ! Code || Befehl || Parameter |- | <code>0b0<span class="hb1">01</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x0B</span></code> || <span class="hb1">Modifier einmal drücken</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Linke Umschalttaste</span>, <span class="hb4">Taste H</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x04</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste A</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x12</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste O</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1100011</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Pause mit 99 Zeiteinheiten</span>: t = (99 + 1) * 5 ms = 500 ms |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb3">0x2C</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Leertaste</span> |- | <code>0b0<span class="hb1">11</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x1A</span></code> || <span class="hb1">Modifier drücken und halten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Rechte Umschalttaste</span>, <span class="hb4">Taste W</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x08</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste E</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x17</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste T</span> |- | <code>0b0<span class="hb1">10</span><span class="hb2">00</span>000</code> || <span class="hb1">Modifier loslassen</span>, <span class="hb2">Kein Tastendruck</span> || - |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x28</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Return-Taste</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1111111</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Ende der der Sequenz</span> |} ===Lesen=== Wie bereits in der Befehlsübersicht erwähnt, erfolgt das Lesen und Schreiben der Sequenzdaten in Blöcken: <code>&gt; <span class="hb1">06</span> <span class="hb2">CC</span> xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> Als Antwort bekommt man dann die Daten des jeweiligen Blocks: <code>&lt; <span class="hb1">86</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Lesen Sequenz (OK)</span> * <span class="hb2">Blocknummer: 0 ... 21 </span> * <span class="hb2">6 Datenbytes des Blocks</span> Ist der letzte Block nicht "füllend", sind die restlichen Bytes zufällig, ebenso kann über das "End of Sequence" hinaus gelesen werden. ===Schreiben=== Das Schreiben von Blöcken ist der Antwort vom Lesen sehr ähnlich: <code>&gt; <span class="hb1">07</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Schreiben Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> * <span class="hb2">6 Datenbytes des Blocks</span> Sobald die Daten geschrieben wurden, antwortet der Mikrocontroller mit: <code>&lt; <span class="hb1">06</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Schreiben Sequenz (OK)</span> ==Modus 3: Gamepad== Es ist keine Konfiguration notwendig, das Gamepad meldet sich mit einer Taste und kann in Anwendungen wie gewohnt zugeordnet werden. <gallery> footswitch_gamepad.png|Eigenschaftenseite in Windows </gallery> Leider erkennt weder Firefox 73 noch Chromium 82 das Pad im html5gamepad-Tester. Anzumerken ist, dass wie bei der Einzeltasten-Tastatur Reports nur bei Zustandsänderung der Taste gesendet werden. Bis jetzt konnte ich dadurch keine Einschränkungen feststellen. =PC-Software= Aktuell gibt es eine kleine Python-Lib und ein paar Beispiele dazu. Siehe Downloads. =Anmerkungen= * Die Firmware auf dem Tiny85 zu entwickeln war grauenvoll, da man nur sehr schlecht debuggen kann. Das nächste Mal lieber auf einem Mikrocontroller mit deutlich mehr IOs und Hardware-UART entwickeln und anschließend auf ein kleineres Geschwister portieren * [https://github.com/micronucleus/micronucleus/ micronucleus] ist ein USB-Bootloader basierend auf V-USB, den ich bis jetzt noch nicht verwendet habe, in Zukunft aber sollte * Der Quellcode steht, wie von objective development gefordert, unter GPLv2 =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= * [[Datei:Footswitch.zip]] Schaltplan & Layout in EAGLE 7.7.0, Firmware & Sourcen in Atmel Studio 7, Beispielanwendung in Python 3.7 =Weblinks= * [https://www.uwe-sieber.de/usbtreeview.html USB Device Tree Viewer] zeigt sehr detaillierte Infos zu angeschlossenen USB-Geräten an * [http://wireshark.org/ Wireshark] kann auch USB tracen * [https://eleccelerator.com/usbdescreqparser/ USB Descriptor and Request Parser] * [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 Universal Serial Bus HID Usage Tables, Seite 53: 10 Keyboard/Keypad Page (0x07)] [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:Kleine Helferlein]] 8918e306289b41c5256038b3b1c01630d93b1872 Datei:Footswitch.zip 6 624 1427 2020-03-01T17:38:32Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbus pi v1.2 3v3.zip 6 625 1434 2020-03-31T18:37:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.1 assy zero.jpg 6 626 1435 2020-03-31T18:38:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.2 assy bot.png 6 627 1436 2020-03-31T18:38:13Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.2 assy top.png 6 628 1437 2020-03-31T18:38:19Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi3v3 100p schwelle1.png 6 629 1438 2020-03-31T18:38:28Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi3v3 100p schwelle2.png 6 630 1439 2020-03-31T18:38:33Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi3v3 100p schwelle3.png 6 631 1440 2020-03-31T18:38:50Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi3v3 100p schwelle4.png 6 632 1441 2020-03-31T18:39:17Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi3v3 100p schwelle5.png 6 633 1442 2020-03-31T18:39:29Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi3v3 delay1.png 6 634 1443 2020-03-31T18:39:41Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi3v3 delay2.png 6 635 1444 2020-03-31T18:39:51Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi3v3 delay3.png 6 636 1445 2020-03-31T18:39:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi3v3 schwelle orig.png 6 637 1446 2020-03-31T18:40:03Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi3v3 vout ripple.png 6 638 1447 2020-03-31T18:40:13Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder 0 120 1448 1408 2020-03-31T18:41:07Z Chris 2 VBusPi v1.2 3v3 hinzugefügt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Troubleshooting== Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. ==Leiterkarten== Es gibt wieder Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =VBus-Adapter für den Raspberry Pi= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.0 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. ==Fehler & Verbesserungen== Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht ==Leiterkarten== Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. ==Weiteres== Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. ==Kostenreduzierte Variante/v1.2== Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ===Die Enttäuschung=== Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ===Die Lösung=== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * IC1: TS5205CX533 * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * R3: 15k * R4: 33k * R6: 15k Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Python-Implementierung= Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie und Gewährleistung: * [[Datei:VBus-Python.zip]] =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano *[[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi *[[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 660f3b25e2eb6effac3bcd0761fc65640fa11f05 1450 1448 2020-03-31T18:45:02Z Chris 2 /* Die Lösung */ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Troubleshooting== Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. ==Leiterkarten== Es gibt wieder Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =VBus-Adapter für den Raspberry Pi= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.0 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. ==Fehler & Verbesserungen== Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht ==Leiterkarten== Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. ==Weiteres== Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. ==Kostenreduzierte Variante/v1.2== Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ===Die Enttäuschung=== Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ===Die Lösung=== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Python-Implementierung= Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie und Gewährleistung: * [[Datei:VBus-Python.zip]] =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano *[[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi *[[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 94e4d4bf779e6426e29e816a60763d323ea011b2 1451 1450 2020-03-31T18:46:07Z Chris 2 /* VBus-Adapter für den Raspberry Pi */ Bildlink korrigiert wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Troubleshooting== Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. ==Leiterkarten== Es gibt wieder Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =VBus-Adapter für den Raspberry Pi= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. ==Fehler & Verbesserungen== Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht ==Leiterkarten== Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. ==Weiteres== Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. ==Kostenreduzierte Variante/v1.2== Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ===Die Enttäuschung=== Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ===Die Lösung=== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Python-Implementierung= Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie und Gewährleistung: * [[Datei:VBus-Python.zip]] =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano *[[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi *[[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] 4df87b3054adefb9e4aa09e757af7d49e821bb9e Datei:Vbuspi3v3 1.2 sch.png 6 639 1449 2020-03-31T18:42:18Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Hauptseite 0 1 1452 1430 2020-03-31T18:48:50Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *31.03.2020 Es geht auch günstiger: [[VBus-Decoder#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] 50ca3e33fbe5e9af2098fc038370cd9fbcfcd91a 1485 1452 2020-04-04T17:56:40Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] d3006bc3b75e5eb9ff464d3f14673ecc6802f55c 1493 1485 2020-04-08T20:27:35Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] a58b8103d68a90888625e6926d7041ec22006b63 1495 1493 2020-04-08T20:28:51Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] c3447e35016956b354726f921edf63d8628ed6da Datei:Cmu restteile.jpg 6 640 1453 2020-04-04T17:45:17Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 boot.jpg 6 641 1454 2020-04-04T17:45:26Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display inverter.jpg 6 642 1455 2020-04-04T17:47:21Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display1.jpg 6 643 1456 2020-04-04T17:47:31Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display2.jpg 6 644 1457 2020-04-04T17:47:38Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display3.jpg 6 645 1458 2020-04-04T17:47:44Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display4.jpg 6 646 1459 2020-04-04T17:47:52Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display5.jpg 6 647 1460 2020-04-04T17:47:59Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display6.jpg 6 648 1461 2020-04-04T17:48:12Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display7.jpg 6 649 1462 2020-04-04T17:48:17Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display8.jpg 6 650 1463 2020-04-04T17:48:22Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display9.jpg 6 651 1464 2020-04-04T17:48:26Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display10.jpg 6 652 1465 2020-04-04T17:48:32Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 embedded pc.jpg 6 653 1466 2020-04-04T17:48:39Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 flachbandkabel.jpg 6 654 1467 2020-04-04T17:48:44Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 hdd1.jpg 6 655 1468 2020-04-04T17:48:57Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 hdd2.jpg 6 656 1469 2020-04-04T17:49:03Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 schrauben1.jpg 6 657 1470 2020-04-04T17:49:10Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 schrauben2.jpg 6 658 1471 2020-04-04T17:49:17Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 schrauben3.jpg 6 659 1472 2020-04-04T17:49:24Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 schrauben4.jpg 6 660 1473 2020-04-04T17:49:33Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 schrauben5.jpg 6 661 1474 2020-04-04T17:49:41Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 schrauben6.jpg 6 662 1475 2020-04-04T17:49:47Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 schrauben7.jpg 6 663 1476 2020-04-04T17:49:52Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 schrauben8.jpg 6 664 1477 2020-04-04T17:49:57Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 schrauben9.jpg 6 665 1478 2020-04-04T17:50:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 vreg1.png 6 666 1479 2020-04-04T17:50:12Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Reparatur R&S CMU200 Hintergrundbeleuchtung 0 669 1482 2020-04-04T17:53:48Z Chris 2 Seite erstellt wikitext text/x-wiki In der Arbeit wurde ein Schwung [https://www.rohde-schwarz.com/de/produkt/cmu200-produkt-startseite_63493-7830.html Rohde und Schwarz CMU200] ausgemustert. Für die, die sie nicht kennen: Eine CMU ist ein "Universal Radio Communication Tester", ausgerichtet auf Mobilfunktelefone. Kurzum: eine kleine Handy-Basisstation mit vielen möglichen Optionen, von GSM über WCDMA und HSPA, ..., aber auch Bluetooth. Das bedeutet aber nicht, dass man mit dem Teil zum Mobilfunkbetreiber werden kann, im Gegenteil: es dürfte ziemlich dumm sein, anstatt eines geschirmten Koppler eine "offene" Antenne anzuschließen. Aber was macht man als Bastler mit dem Teil, außer etwas ältere Technik zu bewundern? Ganz einfach: zu den Basisfunktionen gehören ein relativ gutes Frequenznormal, ein Signalgenerator mit verschiedenen Modulationsarten und ein ordentlicher Spectrum Analyzer. Auf einem der Geräte war ein Aufkleber "Display defekt". Die meisten Displays aus der Zeit haben noch ein eine Hintergrundbeleuchtung mit CCFL-Röhren und viele verwechseln ein kaputtes Display mit einem kaputten Backlight - also ab in den Kofferraum mit dem Teil. Wenn man im zweiten Stock ohne Aufzug wohnt merkt man, wie solide Geräte aus dem Hause Rohde und Schwarz gebaut sind, "das gilt als Sport". Am Strom surren die Lüfter und die Festplatte vor sich hin und das Display bleibt erwartungsgemäß dunkel. Der einfachste Test für LCDs ist, mit der Taschenlampe hineinzuleuchten und siehe da: dunkel schimmert die Benutzeroberfläche. Praktischerweise hat das Teil auch einen VGA-Ausgang, der auch gut funktioniert. Damit wäre der Artikel im Prinzip auch schon zu Ende. Falsch gedacht, er fängt erst an: =Auf das Ding!= Ein kurzer Abstecher [https://duckduckgo.com/?q=CMU200+service+manual ins Internet] fördert Service Manuals zu Tage. Ab der Hälfte des Manuals mit "other" im Namen steht dann sogar, wie man das Gehäuse öffnet: Gehäuse auf die Front legen (sofern die Griffe vorhanden sind) und hinten die Füße mit einem T20 Torx abschrauben. Nun kann man die Hülle herunterziehen und legt den Zugriff zu allen weiteren Schrauben bei. <gallery> cmu200_schrauben1.jpg | Mit einem T20 Schraubendreher und Zielvermögen lassen sich die Füße entfernen </gallery> Hier sieht man auch, wo man das Geld für ein Einfamilienhaus stecken konnte: In Module (und Lizenzen). Um an das Display zu kommen, müssen zunächst die vorderen Griffe ab, die zugleich auch die Frontblende am Gehäuse fixieren. Im Anschluss können die hinteren Schrauben am Frontmodul ringsum und die am Halteblech des nach hinten ragenden Moduls sowie dem PCMCIA-Adapter gelöst werden: <gallery> cmu200_schrauben2.jpg | 5 Schrauben oben, cmu200_schrauben3.jpg | 4 unten cmu200_schrauben4.jpg | und jeweils 2 cmu200_schrauben5.jpg | an den Seiten </gallery> Mit einem vorsichtigen Ruck kann man nun das Frontmodul vom Rest befreien. Je nach Ausbaustufe muss man auch ein paar Flachbandkabel abziehen. Hat man das Frontmodul auf dem Schreibtisch, heißt es wieder: ringsum Schrauben lösen. Allerdings ist man dann noch nicht am Ende: noch einmal darf man rundherum den schraubendreher schwingen. Immerhin: alle Schrauben haben die gleice Größe. <gallery> cmu200_schrauben6.jpg | Leider nur von einer Seite, das Prinzip ist aber klar cmu200_schrauben7.jpg | Endlich am Enbedded-PC angekommen, cmu200_schrauben8.jpg | sofern man willens ist, noch cmu200_schrauben9.jpg | ein paar mehr Schrauben zu drehen </gallery> Jetzt man kann (vorsichtig!) das Display vom Embedded-PC trennen. Am besten zuerst die Verbindung der Folientastatur lösen, anschließend die Flachbandkabel für Display und Jogdial. Leider habe ich hiervon kein Foto gemacht. =Backlight-Tausch== Obwohl ich mich schon darauf eingestellt habe, das Display komplett zu zerlegen ist es durchaus wartungsfreundlich - die Röhre lässt sich als Modul mit zwei Schrauben entfernen: <gallery> cmu200_display1.jpg | Display mit Abdeckung der Röhre cmu200_display2.jpg | Display ohne Abdeckung der Röhre cmu200_display_inverter.jpg | Inverter der Hintergrundbeleuchtung </gallery> Das erste Foto ist leider gestellt - die CCFL habe ich bei erster Gelegenheit entfernt, da die Ausdünstungen bei einem Bruch nicht unbeding gesundheitsförderlich ist. Der Inverter ist auch bei erster Gelegenheit rausgefallen. Der Inverter ist ebenfalls ein eigenes Modul - ein 810-CXA-L0605-VJL von TDK. [https://www.mouser.de/ProductDetail/TDK/CXA-L0605-VJL?qs=lq5%252BOP7PS09Q7ZKD1DX6Kw%3D%3D Mouser] hat sogar noch ein Datenblatt, das ein paar meiner Hoffnungen zerstört. Leider wird das Teil mit 5 Volt und nicht mit LED-Streifen-freundlichen 12 V betrieben. Laut Datenblatt genehmigt sich das Teil bis zu 0,8 A, also 4 Watt. Damit sollte man das Displays mit LEDs sehr hell bekommen. Aber zunächst muss man sie überhaupt montieren können. Der Originalrahmen ist, als hätte es Sharp geahnt, knapp 8 mm tief, sehr passend zu marktüblichen LED-Streifen. Meine Wahl fällt auf das, was rumliegt: kaltweiße Streifen mit 60 PLCC2-LEDs pro Meter. Nicht die hellsten oder besten am Markt, aber sie sind da. Die nächste Frage stellt sich sogleich: wie montieren? Im Baumarkt werde ich fündig: ein [https://www.bauhaus.info/metallprofile-kunststoffprofile/kantoflex-winkelprofil/p/10522351?adb_search=25642 L-Profil mit 7,5 x 12,5 mm], 1 m für 1,45 Euro. Nicht ideal, aber die Welt ist eben voller Kompromisse. Auf 13,5 und 18 cm abgelängt, mit 45° gegehrt passen die Profile sehr gut ans Display - und auch die LED-Streifen passen wie angegossen. Mit etwas Kapton-Tape ist auch sichergestellt, dass es am Ende der Streifen keine Kurzschlüsse gibt. <gallery> cmu200_display3.jpg | gesägte und beklebte Aluprofile cmu200_display4.jpg | mit guter Passform cmu200_display5.jpg | auch wenn man genauer hinschaut </gallery> Bevor die Streifen fixiert werden muss natürlich getestet werden, mit welchem Abstand die Lichtausbeute und Konformität am besten ist. <gallery> cmu200_display6.jpg | Ausleuchtung mit LED-Hintergrundbeleuchtung </gallery> Stellt sich heraus: so nah wie möglich an den Lightspreader. Die auf den Fotos sichtbaren Leuchtpunkte fallen mit bloßem Auge kaum auf. Auch der Grünstich ist nicht ganz so heftig wie auf den Bildern zu sehen ist, aber dennoch vorhanden. Fixiert wird das Ganze nicht nur mit einer Portion Heißkleber, sondern auch mit Alutape - es soll ja nach was aussehen: <gallery> cmu200_display7.jpg | Angeheftet mit Heißkleber cmu200_display8.jpg | Flächenklebung mit Alutape </gallery> ==LED-Treiber== Jetzt müssen nur noch die LEDs getrieben werden. Großartig in der Elektronik herumpopeln möchte ich nicht, wer weiß, wie die Stromversorgungen ausgelegt sind und wie empfindlich manche Rails sind. Da der CCFL-Treiber vermutlich auch nicht wenig herumgesaut hat, fiel die Wahl auf einen kleinen DC-DC-Wandler, der auf einem MT3608 basiert. Das Teil hat nur eine Marotte: Wenn man am Poti dreht, passiert erst sehr wenig, dann plötzlich sehr viel. Schaut man die Spindel nur mal kurz schief an, springt die Spannung von 12 V auf 14 V. Das möchte ich den LEDs nicht zumuten - und ja, LEDs treibt man eigentlich über den Strom. Der Spannungsteiler besteht aus einem 100 kOhm-Poti das gegen Masse über einen 2,2 kOhm-Widerstand "verlängert" ist. Die Ausgangsspannung berechnet sich nach: :<math>U_{\textrm{out}}=U_{\textrm{ref}} \cdot \left(\frac{x\cdot R_{\textrm{pot}}}{(1-x)\cdot R_{\textrm{pot}} + R_{\textrm{bot}}}\right + 1)</math> Mit <math>U_{\textrm{ref}}=0.6\ \textrm{V}</math> erhält man bei einem auf Anschlag gedrehtem Poti (<math>x = 1</math>) einen Wert von 27,87 V. Das ist ein bisschen zu viel. Schaut man sich an, wie sich die Ausgangsspannung über x (also der Potistellung) verhält, merkt man, dass das gar nicht mal so clever gemacht ist: <gallery> cmu200_vreg1.png | Ausgangsspannung in Abhängigkeit der Potistellung - Originalzustand </gallery> Stellt man die oben gezeigte Formel um, kann man mit <math>x = 1</math> und <math>U_{\textrm{out}}</math> als Maximalspannung den nötigen Bottom-Widerstand ermitteln: :<math>R_{\textrm{bot}} = R_{\textrm{pot}} \cdot \left( \frac{U_{\textrm{out}} \cdot x}{U_{\textrm{out}} - U_{\textrm{ref}}} - 1 \right)</math> Für <math>U_{\textrm{out}} = 13\ \textrm{V}</math> erhält man einen Widerstand von 4,8 kOhm, der nächste verfügbare ist 4,7 kOhm. Rechnet man nochmal "rück", kommt man auf eine maximale Ausgangsspannung von etwa 13,37 V. Passt soweit. Erwartungsgemäß verhält sich der Ausgang ähnlich exponentiell wie zuvor: <gallery> cmu200_vreg2.png | Ausgangsspannung in Abhängigkeit der Potistellung - mit 4,7 kOhm-Poti </gallery> Das Problem liegt im Nenner der Funktion: geht x gegen 1, wandert der Nenner gegen klein und die Gesamtfunktion "explodiert". Die Misere lässt sich mit einem Stück Draht beheben: Schließt man den "unteren Teil" des Potis kurz, wird <math>(1-x)\cdot R_{\textrm{pot}}=0</math> und der Term wird linear: <gallery> cmu200_vreg3.png | Ausgangsspannung in Abhängigkeit der Potistellung - mit 4,7 kOhm-Poti und einseitig gebrücktem Poti </gallery> Anhand des Datenblattes des ursprünglichen Treibers der Hintergrundbeleuchtung lässt sich die Pinbelegung ermitteln: Blau ist Schwarz und Schwarz ist rot. Nein: Pin 1 ist Vin und Pin 2 GND. Pin 3 ist ein Remote Enable und an der 4 könnte man die Helligkeit einstellen. "Unwichtig" sagt der Bastler und irgendwo muss der Stecker ja befestigt sein. Damit sich das Poti nicht doch noch umentscheidet, wird die Einstellung mit Heißkleber fixiert. Die Montage im Gehäuse erfolgt über einen etwas länger gelassenen Schrumpfschlauch und der bereits vorhandenen Schraube. Damit nichts herumflattert (und in der Hoffnung, dass es in Sachen EMV hilft) kommt noch eine Lage Alutape drüber: <gallery> cmu200_display9.jpg | Anschluss an den Leitungssatz cmu200_display10.jpg | eingeschrumpft und angeschraubt cmu200_display11.jpg | und verklebt </gallery> ==Wenn man schon dabei ist & Zusammenbau== Obwohl die CMU eher einfach zu Zerlegen ist, dauert es doch eine Weile, bis die Einzelteile auf dem Tisch liegen. Deshalb macht man am besten das, was man an der Stelle gut machen kann: Wartung. Das Lager der Lüfter hört man mittlerweile recht gut, passenden Ersatz habe ich aber nicht da, also bleibt der erst einmal so. Was aber immer geht und nach knapp 20 Jahren doch mal platt sein kann: die BIOS-Batterie. Alte raus, neue rein und wieder einige Jahre Ruhe. <gallery> cmu200_embedded_pc.jpg | Ein Blick auf das Mainboard </gallery> Es empfiehlt sich auch, ein Backup der Festplatte (z. B. mit [https://clonezilla.org/ Clonezilla]) anzulegen. Da es mittlerweile schwierig ist, 2,5"-Festplatten mit P-ATA Interface zu bekommen: CF-Karten mit IDE-Adapter funktionierten zumindest bei einem anderen R&S-Gerät ausgezeichnet, inklusive kürzerer Boot-Zeiten. Wie langlebig ein solcher Aufbau ist - keine Ahnung. Das Zusammenbauen erfolgt genau rückwärts zum Zerlegen, wobei es ein paar Fallstricke gibt: Da die Stiftleiste für die Festplatte keine Wanne hat, muss man darauf achten, dass der Stecker richtig sitzt. Was auf dem ersten Blick ok aussieht, kann in Tränen enden: <gallery> cmu200_hdd1.jpg | sieht richtig aus cmu200_hdd2.jpg | ist aber falsch </gallery> Beim Aufstecken des Frontmoduls "darf" man unter Umständen ein paar Flachbandkabel einstecken, die allerdings passend beschriftet sind: <gallery> cmu200_flachbandkabel.jpg | W222 auf X222 </gallery> Etwas fummelig ist das auf jeden Fall vorhandene für die LEDs am Frontpanel - hier gibt es leider kein Patentrezept. Ich habe mit der einen Hand das Panel gehalten und mit der anderen das Kabel von unten in die richtige Position manövriert. Nun kommt auch die Stunde der Wahrheit: Noch bevor man den Deckel schließt, sollte man prüfen, ob die Kiste hochkommt. <gallery> cmu200_boot.jpg | Erfolg! </gallery> Im Anschluss packt man die übrig gebliebenen Schrauben in eine kleine Tüte und klebt sie mit Klebeband so auf die Abdeckung, dass sie nach unten herunterbaumeln. <gallery> cmu_restteile.jpg </gallery> Oder man sucht, wo sie tatsächlich hingehören, z. B. ans Bracket des PCMCIA-Slots und dem Niederhalter für die Einsteckkarte. [[Kategorie:Messequipment]] [[Kategorie:Reparatur]] [[Kategorie:Elektronik]] 935bf5abd9e51c6d81a1751ca39ee3007475e369 1483 1482 2020-04-04T17:54:30Z Chris 2 wikitext text/x-wiki In der Arbeit wurde ein Schwung [https://www.rohde-schwarz.com/de/produkt/cmu200-produkt-startseite_63493-7830.html Rohde und Schwarz CMU200] ausgemustert. Für die, die sie nicht kennen: Eine CMU ist ein "Universal Radio Communication Tester", ausgerichtet auf Mobilfunktelefone. Kurzum: eine kleine Handy-Basisstation mit vielen möglichen Optionen, von GSM über WCDMA und HSPA, ..., aber auch Bluetooth. Das bedeutet aber nicht, dass man mit dem Teil zum Mobilfunkbetreiber werden kann, im Gegenteil: es dürfte ziemlich dumm sein, anstatt eines geschirmten Koppler eine "offene" Antenne anzuschließen. Aber was macht man als Bastler mit dem Teil, außer etwas ältere Technik zu bewundern? Ganz einfach: zu den Basisfunktionen gehören ein relativ gutes Frequenznormal, ein Signalgenerator mit verschiedenen Modulationsarten und ein ordentlicher Spectrum Analyzer. Auf einem der Geräte war ein Aufkleber "Display defekt". Die meisten Displays aus der Zeit haben noch ein eine Hintergrundbeleuchtung mit CCFL-Röhren und viele verwechseln ein kaputtes Display mit einem kaputten Backlight - also ab in den Kofferraum mit dem Teil. Wenn man im zweiten Stock ohne Aufzug wohnt merkt man, wie solide Geräte aus dem Hause Rohde und Schwarz gebaut sind, "das gilt als Sport". Am Strom surren die Lüfter und die Festplatte vor sich hin und das Display bleibt erwartungsgemäß dunkel. Der einfachste Test für LCDs ist, mit der Taschenlampe hineinzuleuchten und siehe da: dunkel schimmert die Benutzeroberfläche. Praktischerweise hat das Teil auch einen VGA-Ausgang, der auch gut funktioniert. Damit wäre der Artikel im Prinzip auch schon zu Ende. Falsch gedacht, er fängt erst an: =Auf das Ding!= Ein kurzer Abstecher [https://duckduckgo.com/?q=CMU200+service+manual ins Internet] fördert Service Manuals zu Tage. Ab der Hälfte des Manuals mit "other" im Namen steht dann sogar, wie man das Gehäuse öffnet: Gehäuse auf die Front legen (sofern die Griffe vorhanden sind) und hinten die Füße mit einem T20 Torx abschrauben. Nun kann man die Hülle herunterziehen und legt den Zugriff zu allen weiteren Schrauben bei. <gallery> cmu200_schrauben1.jpg | Mit einem T20 Schraubendreher und Zielvermögen lassen sich die Füße entfernen </gallery> Hier sieht man auch, wo man das Geld für ein Einfamilienhaus stecken konnte: In Module (und Lizenzen). Um an das Display zu kommen, müssen zunächst die vorderen Griffe ab, die zugleich auch die Frontblende am Gehäuse fixieren. Im Anschluss können die hinteren Schrauben am Frontmodul ringsum und die am Halteblech des nach hinten ragenden Moduls sowie dem PCMCIA-Adapter gelöst werden: <gallery> cmu200_schrauben2.jpg | 5 Schrauben oben, cmu200_schrauben3.jpg | 4 unten cmu200_schrauben4.jpg | und jeweils 2 cmu200_schrauben5.jpg | an den Seiten </gallery> Mit einem vorsichtigen Ruck kann man nun das Frontmodul vom Rest befreien. Je nach Ausbaustufe muss man auch ein paar Flachbandkabel abziehen. Hat man das Frontmodul auf dem Schreibtisch, heißt es wieder: ringsum Schrauben lösen. Allerdings ist man dann noch nicht am Ende: noch einmal darf man rundherum den schraubendreher schwingen. Immerhin: alle Schrauben haben die gleice Größe. <gallery> cmu200_schrauben6.jpg | Leider nur von einer Seite, das Prinzip ist aber klar cmu200_schrauben7.jpg | Endlich am Enbedded-PC angekommen, cmu200_schrauben8.jpg | sofern man willens ist, noch cmu200_schrauben9.jpg | ein paar mehr Schrauben zu drehen </gallery> Jetzt man kann (vorsichtig!) das Display vom Embedded-PC trennen. Am besten zuerst die Verbindung der Folientastatur lösen, anschließend die Flachbandkabel für Display und Jogdial. Leider habe ich hiervon kein Foto gemacht. =Backlight-Tausch= Obwohl ich mich schon darauf eingestellt habe, das Display komplett zu zerlegen ist es durchaus wartungsfreundlich - die Röhre lässt sich als Modul mit zwei Schrauben entfernen: <gallery> cmu200_display1.jpg | Display mit Abdeckung der Röhre cmu200_display2.jpg | Display ohne Abdeckung der Röhre cmu200_display_inverter.jpg | Inverter der Hintergrundbeleuchtung </gallery> Das erste Foto ist leider gestellt - die CCFL habe ich bei erster Gelegenheit entfernt, da die Ausdünstungen bei einem Bruch nicht unbeding gesundheitsförderlich ist. Der Inverter ist auch bei erster Gelegenheit rausgefallen. Der Inverter ist ebenfalls ein eigenes Modul - ein 810-CXA-L0605-VJL von TDK. [https://www.mouser.de/ProductDetail/TDK/CXA-L0605-VJL?qs=lq5%252BOP7PS09Q7ZKD1DX6Kw%3D%3D Mouser] hat sogar noch ein Datenblatt, das ein paar meiner Hoffnungen zerstört. Leider wird das Teil mit 5 Volt und nicht mit LED-Streifen-freundlichen 12 V betrieben. Laut Datenblatt genehmigt sich das Teil bis zu 0,8 A, also 4 Watt. Damit sollte man das Displays mit LEDs sehr hell bekommen. Aber zunächst muss man sie überhaupt montieren können. Der Originalrahmen ist, als hätte es Sharp geahnt, knapp 8 mm tief, sehr passend zu marktüblichen LED-Streifen. Meine Wahl fällt auf das, was rumliegt: kaltweiße Streifen mit 60 PLCC2-LEDs pro Meter. Nicht die hellsten oder besten am Markt, aber sie sind da. Die nächste Frage stellt sich sogleich: wie montieren? Im Baumarkt werde ich fündig: ein [https://www.bauhaus.info/metallprofile-kunststoffprofile/kantoflex-winkelprofil/p/10522351?adb_search=25642 L-Profil mit 7,5 x 12,5 mm], 1 m für 1,45 Euro. Nicht ideal, aber die Welt ist eben voller Kompromisse. Auf 13,5 und 18 cm abgelängt, mit 45° gegehrt passen die Profile sehr gut ans Display - und auch die LED-Streifen passen wie angegossen. Mit etwas Kapton-Tape ist auch sichergestellt, dass es am Ende der Streifen keine Kurzschlüsse gibt. <gallery> cmu200_display3.jpg | gesägte und beklebte Aluprofile cmu200_display4.jpg | mit guter Passform cmu200_display5.jpg | auch wenn man genauer hinschaut </gallery> Bevor die Streifen fixiert werden muss natürlich getestet werden, mit welchem Abstand die Lichtausbeute und Konformität am besten ist. <gallery> cmu200_display6.jpg | Ausleuchtung mit LED-Hintergrundbeleuchtung </gallery> Stellt sich heraus: so nah wie möglich an den Lightspreader. Die auf den Fotos sichtbaren Leuchtpunkte fallen mit bloßem Auge kaum auf. Auch der Grünstich ist nicht ganz so heftig wie auf den Bildern zu sehen ist, aber dennoch vorhanden. Fixiert wird das Ganze nicht nur mit einer Portion Heißkleber, sondern auch mit Alutape - es soll ja nach was aussehen: <gallery> cmu200_display7.jpg | Angeheftet mit Heißkleber cmu200_display8.jpg | Flächenklebung mit Alutape </gallery> =LED-Treiber= Jetzt müssen nur noch die LEDs getrieben werden. Großartig in der Elektronik herumpopeln möchte ich nicht, wer weiß, wie die Stromversorgungen ausgelegt sind und wie empfindlich manche Rails sind. Da der CCFL-Treiber vermutlich auch nicht wenig herumgesaut hat, fiel die Wahl auf einen kleinen DC-DC-Wandler, der auf einem MT3608 basiert. Das Teil hat nur eine Marotte: Wenn man am Poti dreht, passiert erst sehr wenig, dann plötzlich sehr viel. Schaut man die Spindel nur mal kurz schief an, springt die Spannung von 12 V auf 14 V. Das möchte ich den LEDs nicht zumuten - und ja, LEDs treibt man eigentlich über den Strom. Der Spannungsteiler besteht aus einem 100 kOhm-Poti das gegen Masse über einen 2,2 kOhm-Widerstand "verlängert" ist. Die Ausgangsspannung berechnet sich nach: :<math>U_{\textrm{out}}=U_{\textrm{ref}} \cdot \left(\frac{x\cdot R_{\textrm{pot}}}{(1-x)\cdot R_{\textrm{pot}} + R_{\textrm{bot}}}\right + 1)</math> Mit <math>U_{\textrm{ref}}=0.6\ \textrm{V}</math> erhält man bei einem auf Anschlag gedrehtem Poti (<math>x = 1</math>) einen Wert von 27,87 V. Das ist ein bisschen zu viel. Schaut man sich an, wie sich die Ausgangsspannung über x (also der Potistellung) verhält, merkt man, dass das gar nicht mal so clever gemacht ist: <gallery> cmu200_vreg1.png | Ausgangsspannung in Abhängigkeit der Potistellung - Originalzustand </gallery> Stellt man die oben gezeigte Formel um, kann man mit <math>x = 1</math> und <math>U_{\textrm{out}}</math> als Maximalspannung den nötigen Bottom-Widerstand ermitteln: :<math>R_{\textrm{bot}} = R_{\textrm{pot}} \cdot \left( \frac{U_{\textrm{out}} \cdot x}{U_{\textrm{out}} - U_{\textrm{ref}}} - 1 \right)</math> Für <math>U_{\textrm{out}} = 13\ \textrm{V}</math> erhält man einen Widerstand von 4,8 kOhm, der nächste verfügbare ist 4,7 kOhm. Rechnet man nochmal "rück", kommt man auf eine maximale Ausgangsspannung von etwa 13,37 V. Passt soweit. Erwartungsgemäß verhält sich der Ausgang ähnlich exponentiell wie zuvor: <gallery> cmu200_vreg2.png | Ausgangsspannung in Abhängigkeit der Potistellung - mit 4,7 kOhm-Poti </gallery> Das Problem liegt im Nenner der Funktion: geht x gegen 1, wandert der Nenner gegen klein und die Gesamtfunktion "explodiert". Die Misere lässt sich mit einem Stück Draht beheben: Schließt man den "unteren Teil" des Potis kurz, wird <math>(1-x)\cdot R_{\textrm{pot}}=0</math> und der Term wird linear: <gallery> cmu200_vreg3.png | Ausgangsspannung in Abhängigkeit der Potistellung - mit 4,7 kOhm-Poti und einseitig gebrücktem Poti </gallery> Anhand des Datenblattes des ursprünglichen Treibers der Hintergrundbeleuchtung lässt sich die Pinbelegung ermitteln: Blau ist Schwarz und Schwarz ist rot. Nein: Pin 1 ist Vin und Pin 2 GND. Pin 3 ist ein Remote Enable und an der 4 könnte man die Helligkeit einstellen. "Unwichtig" sagt der Bastler und irgendwo muss der Stecker ja befestigt sein. Damit sich das Poti nicht doch noch umentscheidet, wird die Einstellung mit Heißkleber fixiert. Die Montage im Gehäuse erfolgt über einen etwas länger gelassenen Schrumpfschlauch und der bereits vorhandenen Schraube. Damit nichts herumflattert (und in der Hoffnung, dass es in Sachen EMV hilft) kommt noch eine Lage Alutape drüber: <gallery> cmu200_display9.jpg | Anschluss an den Leitungssatz cmu200_display10.jpg | eingeschrumpft und angeschraubt cmu200_display11.jpg | und verklebt </gallery> =Wenn man schon dabei ist & Zusammenbau= Obwohl die CMU eher einfach zu Zerlegen ist, dauert es doch eine Weile, bis die Einzelteile auf dem Tisch liegen. Deshalb macht man am besten das, was man an der Stelle gut machen kann: Wartung. Das Lager der Lüfter hört man mittlerweile recht gut, passenden Ersatz habe ich aber nicht da, also bleibt der erst einmal so. Was aber immer geht und nach knapp 20 Jahren doch mal platt sein kann: die BIOS-Batterie. Alte raus, neue rein und wieder einige Jahre Ruhe. <gallery> cmu200_embedded_pc.jpg | Ein Blick auf das Mainboard </gallery> Es empfiehlt sich auch, ein Backup der Festplatte (z. B. mit [https://clonezilla.org/ Clonezilla]) anzulegen. Da es mittlerweile schwierig ist, 2,5"-Festplatten mit P-ATA Interface zu bekommen: CF-Karten mit IDE-Adapter funktionierten zumindest bei einem anderen R&S-Gerät ausgezeichnet, inklusive kürzerer Boot-Zeiten. Wie langlebig ein solcher Aufbau ist - keine Ahnung. Das Zusammenbauen erfolgt genau rückwärts zum Zerlegen, wobei es ein paar Fallstricke gibt: Da die Stiftleiste für die Festplatte keine Wanne hat, muss man darauf achten, dass der Stecker richtig sitzt. Was auf dem ersten Blick ok aussieht, kann in Tränen enden: <gallery> cmu200_hdd1.jpg | sieht richtig aus cmu200_hdd2.jpg | ist aber falsch </gallery> Beim Aufstecken des Frontmoduls "darf" man unter Umständen ein paar Flachbandkabel einstecken, die allerdings passend beschriftet sind: <gallery> cmu200_flachbandkabel.jpg | W222 auf X222 </gallery> Etwas fummelig ist das auf jeden Fall vorhandene für die LEDs am Frontpanel - hier gibt es leider kein Patentrezept. Ich habe mit der einen Hand das Panel gehalten und mit der anderen das Kabel von unten in die richtige Position manövriert. Nun kommt auch die Stunde der Wahrheit: Noch bevor man den Deckel schließt, sollte man prüfen, ob die Kiste hochkommt. <gallery> cmu200_boot.jpg | Erfolg! </gallery> Im Anschluss packt man die übrig gebliebenen Schrauben in eine kleine Tüte und klebt sie mit Klebeband so auf die Abdeckung, dass sie nach unten herunterbaumeln. <gallery> cmu_restteile.jpg </gallery> Oder man sucht, wo sie tatsächlich hingehören, z. B. ans Bracket des PCMCIA-Slots und dem Niederhalter für die Einsteckkarte. [[Kategorie:Messequipment]] [[Kategorie:Reparatur]] [[Kategorie:Elektronik]] 0f5ab8772aaa3e826d58aa13e781b7c038a1562e 1484 1483 2020-04-04T17:54:58Z Chris 2 /* LED-Treiber */ Formel korrigiert wikitext text/x-wiki In der Arbeit wurde ein Schwung [https://www.rohde-schwarz.com/de/produkt/cmu200-produkt-startseite_63493-7830.html Rohde und Schwarz CMU200] ausgemustert. Für die, die sie nicht kennen: Eine CMU ist ein "Universal Radio Communication Tester", ausgerichtet auf Mobilfunktelefone. Kurzum: eine kleine Handy-Basisstation mit vielen möglichen Optionen, von GSM über WCDMA und HSPA, ..., aber auch Bluetooth. Das bedeutet aber nicht, dass man mit dem Teil zum Mobilfunkbetreiber werden kann, im Gegenteil: es dürfte ziemlich dumm sein, anstatt eines geschirmten Koppler eine "offene" Antenne anzuschließen. Aber was macht man als Bastler mit dem Teil, außer etwas ältere Technik zu bewundern? Ganz einfach: zu den Basisfunktionen gehören ein relativ gutes Frequenznormal, ein Signalgenerator mit verschiedenen Modulationsarten und ein ordentlicher Spectrum Analyzer. Auf einem der Geräte war ein Aufkleber "Display defekt". Die meisten Displays aus der Zeit haben noch ein eine Hintergrundbeleuchtung mit CCFL-Röhren und viele verwechseln ein kaputtes Display mit einem kaputten Backlight - also ab in den Kofferraum mit dem Teil. Wenn man im zweiten Stock ohne Aufzug wohnt merkt man, wie solide Geräte aus dem Hause Rohde und Schwarz gebaut sind, "das gilt als Sport". Am Strom surren die Lüfter und die Festplatte vor sich hin und das Display bleibt erwartungsgemäß dunkel. Der einfachste Test für LCDs ist, mit der Taschenlampe hineinzuleuchten und siehe da: dunkel schimmert die Benutzeroberfläche. Praktischerweise hat das Teil auch einen VGA-Ausgang, der auch gut funktioniert. Damit wäre der Artikel im Prinzip auch schon zu Ende. Falsch gedacht, er fängt erst an: =Auf das Ding!= Ein kurzer Abstecher [https://duckduckgo.com/?q=CMU200+service+manual ins Internet] fördert Service Manuals zu Tage. Ab der Hälfte des Manuals mit "other" im Namen steht dann sogar, wie man das Gehäuse öffnet: Gehäuse auf die Front legen (sofern die Griffe vorhanden sind) und hinten die Füße mit einem T20 Torx abschrauben. Nun kann man die Hülle herunterziehen und legt den Zugriff zu allen weiteren Schrauben bei. <gallery> cmu200_schrauben1.jpg | Mit einem T20 Schraubendreher und Zielvermögen lassen sich die Füße entfernen </gallery> Hier sieht man auch, wo man das Geld für ein Einfamilienhaus stecken konnte: In Module (und Lizenzen). Um an das Display zu kommen, müssen zunächst die vorderen Griffe ab, die zugleich auch die Frontblende am Gehäuse fixieren. Im Anschluss können die hinteren Schrauben am Frontmodul ringsum und die am Halteblech des nach hinten ragenden Moduls sowie dem PCMCIA-Adapter gelöst werden: <gallery> cmu200_schrauben2.jpg | 5 Schrauben oben, cmu200_schrauben3.jpg | 4 unten cmu200_schrauben4.jpg | und jeweils 2 cmu200_schrauben5.jpg | an den Seiten </gallery> Mit einem vorsichtigen Ruck kann man nun das Frontmodul vom Rest befreien. Je nach Ausbaustufe muss man auch ein paar Flachbandkabel abziehen. Hat man das Frontmodul auf dem Schreibtisch, heißt es wieder: ringsum Schrauben lösen. Allerdings ist man dann noch nicht am Ende: noch einmal darf man rundherum den schraubendreher schwingen. Immerhin: alle Schrauben haben die gleice Größe. <gallery> cmu200_schrauben6.jpg | Leider nur von einer Seite, das Prinzip ist aber klar cmu200_schrauben7.jpg | Endlich am Enbedded-PC angekommen, cmu200_schrauben8.jpg | sofern man willens ist, noch cmu200_schrauben9.jpg | ein paar mehr Schrauben zu drehen </gallery> Jetzt man kann (vorsichtig!) das Display vom Embedded-PC trennen. Am besten zuerst die Verbindung der Folientastatur lösen, anschließend die Flachbandkabel für Display und Jogdial. Leider habe ich hiervon kein Foto gemacht. =Backlight-Tausch= Obwohl ich mich schon darauf eingestellt habe, das Display komplett zu zerlegen ist es durchaus wartungsfreundlich - die Röhre lässt sich als Modul mit zwei Schrauben entfernen: <gallery> cmu200_display1.jpg | Display mit Abdeckung der Röhre cmu200_display2.jpg | Display ohne Abdeckung der Röhre cmu200_display_inverter.jpg | Inverter der Hintergrundbeleuchtung </gallery> Das erste Foto ist leider gestellt - die CCFL habe ich bei erster Gelegenheit entfernt, da die Ausdünstungen bei einem Bruch nicht unbeding gesundheitsförderlich ist. Der Inverter ist auch bei erster Gelegenheit rausgefallen. Der Inverter ist ebenfalls ein eigenes Modul - ein 810-CXA-L0605-VJL von TDK. [https://www.mouser.de/ProductDetail/TDK/CXA-L0605-VJL?qs=lq5%252BOP7PS09Q7ZKD1DX6Kw%3D%3D Mouser] hat sogar noch ein Datenblatt, das ein paar meiner Hoffnungen zerstört. Leider wird das Teil mit 5 Volt und nicht mit LED-Streifen-freundlichen 12 V betrieben. Laut Datenblatt genehmigt sich das Teil bis zu 0,8 A, also 4 Watt. Damit sollte man das Displays mit LEDs sehr hell bekommen. Aber zunächst muss man sie überhaupt montieren können. Der Originalrahmen ist, als hätte es Sharp geahnt, knapp 8 mm tief, sehr passend zu marktüblichen LED-Streifen. Meine Wahl fällt auf das, was rumliegt: kaltweiße Streifen mit 60 PLCC2-LEDs pro Meter. Nicht die hellsten oder besten am Markt, aber sie sind da. Die nächste Frage stellt sich sogleich: wie montieren? Im Baumarkt werde ich fündig: ein [https://www.bauhaus.info/metallprofile-kunststoffprofile/kantoflex-winkelprofil/p/10522351?adb_search=25642 L-Profil mit 7,5 x 12,5 mm], 1 m für 1,45 Euro. Nicht ideal, aber die Welt ist eben voller Kompromisse. Auf 13,5 und 18 cm abgelängt, mit 45° gegehrt passen die Profile sehr gut ans Display - und auch die LED-Streifen passen wie angegossen. Mit etwas Kapton-Tape ist auch sichergestellt, dass es am Ende der Streifen keine Kurzschlüsse gibt. <gallery> cmu200_display3.jpg | gesägte und beklebte Aluprofile cmu200_display4.jpg | mit guter Passform cmu200_display5.jpg | auch wenn man genauer hinschaut </gallery> Bevor die Streifen fixiert werden muss natürlich getestet werden, mit welchem Abstand die Lichtausbeute und Konformität am besten ist. <gallery> cmu200_display6.jpg | Ausleuchtung mit LED-Hintergrundbeleuchtung </gallery> Stellt sich heraus: so nah wie möglich an den Lightspreader. Die auf den Fotos sichtbaren Leuchtpunkte fallen mit bloßem Auge kaum auf. Auch der Grünstich ist nicht ganz so heftig wie auf den Bildern zu sehen ist, aber dennoch vorhanden. Fixiert wird das Ganze nicht nur mit einer Portion Heißkleber, sondern auch mit Alutape - es soll ja nach was aussehen: <gallery> cmu200_display7.jpg | Angeheftet mit Heißkleber cmu200_display8.jpg | Flächenklebung mit Alutape </gallery> =LED-Treiber= Jetzt müssen nur noch die LEDs getrieben werden. Großartig in der Elektronik herumpopeln möchte ich nicht, wer weiß, wie die Stromversorgungen ausgelegt sind und wie empfindlich manche Rails sind. Da der CCFL-Treiber vermutlich auch nicht wenig herumgesaut hat, fiel die Wahl auf einen kleinen DC-DC-Wandler, der auf einem MT3608 basiert. Das Teil hat nur eine Marotte: Wenn man am Poti dreht, passiert erst sehr wenig, dann plötzlich sehr viel. Schaut man die Spindel nur mal kurz schief an, springt die Spannung von 12 V auf 14 V. Das möchte ich den LEDs nicht zumuten - und ja, LEDs treibt man eigentlich über den Strom. Der Spannungsteiler besteht aus einem 100 kOhm-Poti das gegen Masse über einen 2,2 kOhm-Widerstand "verlängert" ist. Die Ausgangsspannung berechnet sich nach: :<math>U_{\textrm{out}}=U_{\textrm{ref}} \cdot \left(\frac{x\cdot R_{\textrm{pot}}}{(1-x)\cdot R_{\textrm{pot}} + R_{\textrm{bot}}} + 1\right)</math> Mit <math>U_{\textrm{ref}}=0.6\ \textrm{V}</math> erhält man bei einem auf Anschlag gedrehtem Poti (<math>x = 1</math>) einen Wert von 27,87 V. Das ist ein bisschen zu viel. Schaut man sich an, wie sich die Ausgangsspannung über x (also der Potistellung) verhält, merkt man, dass das gar nicht mal so clever gemacht ist: <gallery> cmu200_vreg1.png | Ausgangsspannung in Abhängigkeit der Potistellung - Originalzustand </gallery> Stellt man die oben gezeigte Formel um, kann man mit <math>x = 1</math> und <math>U_{\textrm{out}}</math> als Maximalspannung den nötigen Bottom-Widerstand ermitteln: :<math>R_{\textrm{bot}} = R_{\textrm{pot}} \cdot \left( \frac{U_{\textrm{out}} \cdot x}{U_{\textrm{out}} - U_{\textrm{ref}}} - 1 \right)</math> Für <math>U_{\textrm{out}} = 13\ \textrm{V}</math> erhält man einen Widerstand von 4,8 kOhm, der nächste verfügbare ist 4,7 kOhm. Rechnet man nochmal "rück", kommt man auf eine maximale Ausgangsspannung von etwa 13,37 V. Passt soweit. Erwartungsgemäß verhält sich der Ausgang ähnlich exponentiell wie zuvor: <gallery> cmu200_vreg2.png | Ausgangsspannung in Abhängigkeit der Potistellung - mit 4,7 kOhm-Poti </gallery> Das Problem liegt im Nenner der Funktion: geht x gegen 1, wandert der Nenner gegen klein und die Gesamtfunktion "explodiert". Die Misere lässt sich mit einem Stück Draht beheben: Schließt man den "unteren Teil" des Potis kurz, wird <math>(1-x)\cdot R_{\textrm{pot}}=0</math> und der Term wird linear: <gallery> cmu200_vreg3.png | Ausgangsspannung in Abhängigkeit der Potistellung - mit 4,7 kOhm-Poti und einseitig gebrücktem Poti </gallery> Anhand des Datenblattes des ursprünglichen Treibers der Hintergrundbeleuchtung lässt sich die Pinbelegung ermitteln: Blau ist Schwarz und Schwarz ist rot. Nein: Pin 1 ist Vin und Pin 2 GND. Pin 3 ist ein Remote Enable und an der 4 könnte man die Helligkeit einstellen. "Unwichtig" sagt der Bastler und irgendwo muss der Stecker ja befestigt sein. Damit sich das Poti nicht doch noch umentscheidet, wird die Einstellung mit Heißkleber fixiert. Die Montage im Gehäuse erfolgt über einen etwas länger gelassenen Schrumpfschlauch und der bereits vorhandenen Schraube. Damit nichts herumflattert (und in der Hoffnung, dass es in Sachen EMV hilft) kommt noch eine Lage Alutape drüber: <gallery> cmu200_display9.jpg | Anschluss an den Leitungssatz cmu200_display10.jpg | eingeschrumpft und angeschraubt cmu200_display11.jpg | und verklebt </gallery> =Wenn man schon dabei ist & Zusammenbau= Obwohl die CMU eher einfach zu Zerlegen ist, dauert es doch eine Weile, bis die Einzelteile auf dem Tisch liegen. Deshalb macht man am besten das, was man an der Stelle gut machen kann: Wartung. Das Lager der Lüfter hört man mittlerweile recht gut, passenden Ersatz habe ich aber nicht da, also bleibt der erst einmal so. Was aber immer geht und nach knapp 20 Jahren doch mal platt sein kann: die BIOS-Batterie. Alte raus, neue rein und wieder einige Jahre Ruhe. <gallery> cmu200_embedded_pc.jpg | Ein Blick auf das Mainboard </gallery> Es empfiehlt sich auch, ein Backup der Festplatte (z. B. mit [https://clonezilla.org/ Clonezilla]) anzulegen. Da es mittlerweile schwierig ist, 2,5"-Festplatten mit P-ATA Interface zu bekommen: CF-Karten mit IDE-Adapter funktionierten zumindest bei einem anderen R&S-Gerät ausgezeichnet, inklusive kürzerer Boot-Zeiten. Wie langlebig ein solcher Aufbau ist - keine Ahnung. Das Zusammenbauen erfolgt genau rückwärts zum Zerlegen, wobei es ein paar Fallstricke gibt: Da die Stiftleiste für die Festplatte keine Wanne hat, muss man darauf achten, dass der Stecker richtig sitzt. Was auf dem ersten Blick ok aussieht, kann in Tränen enden: <gallery> cmu200_hdd1.jpg | sieht richtig aus cmu200_hdd2.jpg | ist aber falsch </gallery> Beim Aufstecken des Frontmoduls "darf" man unter Umständen ein paar Flachbandkabel einstecken, die allerdings passend beschriftet sind: <gallery> cmu200_flachbandkabel.jpg | W222 auf X222 </gallery> Etwas fummelig ist das auf jeden Fall vorhandene für die LEDs am Frontpanel - hier gibt es leider kein Patentrezept. Ich habe mit der einen Hand das Panel gehalten und mit der anderen das Kabel von unten in die richtige Position manövriert. Nun kommt auch die Stunde der Wahrheit: Noch bevor man den Deckel schließt, sollte man prüfen, ob die Kiste hochkommt. <gallery> cmu200_boot.jpg | Erfolg! </gallery> Im Anschluss packt man die übrig gebliebenen Schrauben in eine kleine Tüte und klebt sie mit Klebeband so auf die Abdeckung, dass sie nach unten herunterbaumeln. <gallery> cmu_restteile.jpg </gallery> Oder man sucht, wo sie tatsächlich hingehören, z. B. ans Bracket des PCMCIA-Slots und dem Niederhalter für die Einsteckkarte. [[Kategorie:Messequipment]] [[Kategorie:Reparatur]] [[Kategorie:Elektronik]] 42c72872590c9e6f79413c01e7a6a02596b4138d Datei:Cmu200 vreg2.png 6 670 1486 2020-04-04T18:34:36Z Qsysopr 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 vreg3.png 6 671 1487 2020-04-04T18:34:50Z Qsysopr 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Cmu200 display11.jpg 6 672 1488 2020-04-04T18:35:26Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Mikrohalter1.jpg 6 673 1489 2020-04-08T19:56:50Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Mikrohalter2.jpg 6 674 1490 2020-04-08T19:56:59Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Mikrohalter.zip 6 675 1491 2020-04-08T19:57:56Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 3D-Druck-Sammelsurium 0 598 1492 1386 2020-04-08T20:26:01Z Chris 2 Mikrohalter hinzugefügt wikitext text/x-wiki =Raspberry Pi Zero Spacer= HATs halten auf dem Raspberry Pi zwar über die Stiftleiste schon relativ gut, allerdings ist es doch eine etwas wackelige Angelegenheit. Mit den Buchsen- und Stiftleisten, die ich verwende (die ebenfalls denen von Reichelt entsprechen dürften), ist der Abstand zwischen den Leiterkarten 11 mm. Solche hat Reichelt aktuell leider nicht im Programm. Warum also nicht selber machen? Einfach nur Distanzbolzen zu drucken ist natürlich langweilig - zudem rollen sie schnell vom Tisch und das anbringen ist eher fummelig. Ein Steg wirkt da Wunder. Am schnellsten (und ohne Materialverschwendung) funktioniert das, wenn er direkt auf der Grundplatte aufliegt. Allerdings ist er dann bei einigen HATs im Weg, daher gibt es zwei Versionen, einmal aufliegend und einmal mit 2 mm Abstand zur Unterseite: <gallery> rpizero_spacers.jpg|Beide Versionen des Abstandshalters rpizero_spacer_flat.jpg|Verbauter flacher Abstandshalter rpizero_spacer_lifted.jpg|Verbauter angehobener Abstandshalter </gallery> Als Schrauben dürften sich am besten M2,5x16 eignen. ==Download== * [[Datei:rpizero_spacer.zip|Download]] Design aus Sketchup Make 2017 & STL-Dateien =Diamex AVR-Prog Bodenplatte= Der AVR-Prog ist funktional ein echt schönes Stück Hardware, kommt aber leider komplett ohne Gehäuse. Hat man wie ich einen eher unordentlichen Schreibtisch, ist die Gefahr durch Kurzschlüsse verdammt groß. Deshalb habe ich eine kleine Bodenplatte erstellt, die man auch mit einer M2x6 Senkkopfschraube (bitte nur mit Kunststoffmutter) fixieren kann. <gallery> Backplate_diamex_avr-prog.jpg|AVR-Prog mit angeschnappter Bodenplatte (und gebrochenem Haken) </gallery> Achtung: Die Toleranzen sind sehr eng gewählt, Nacharbeiten können nötig sein. ==Download== * [[Datei:backplate_all-avr.zip|Download]] Design aus Sketchup Make 2017 & STL-Datei =USB-I²C-Bridge Bodenplatte= Ein bisschen mehr Schutz gibt es auch für die [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge|USB-I²C-Bridge]] <gallery> Backplate_mcp_usb_i2c.jpg|Sieht auch transparent schick aus </gallery> Zum Anbringen einfach auf der Seite mit den beiden Schnapphaken einfädeln, die andere Seite mit einem Schraubendreher bisschen aufbiegen und die Leiterkarte eindrücken. Achtung: Die Toleranzen sind sehr eng gewählt, Nacharbeiten können nötig sein. ==Download== * [[Datei:backplate_mcp_i2c_v1.zip|Download]] Design aus FreeCAD 0.18 (nicht voll parametrisch!) & STL-Datei =Mikrofonarm für den H2n= Aufgrund der Pandemie 2020 (deren Namen ich nicht nennen möchte) sitze ich schon eine Weile im Homeoffice. Da die ganzen Meetings nun online stattfinden, brauche ich Mikrofon und Kopfhörer. Da mein Bluetooth-Headset auf lausige Telefonqualität abfällt, verwende ich meinen treuen Zoom H2n als Mikrofon und Kopfhörer-DAC. Die ersten Zwei Wochen stand es auf einem kleinen Dreibein bzw. einem Gorilla Pod zwischen Mund und Tastatur. Etwas umständlich, wenn man während der Telkos tippen will/muss und man muss jedes Mal nach unten greifen, wenn spontan jemand anruft. Für einen Versuch, eine Arbeitsleuchte selbst zu bauen, habe ich mir vor einiger Zeit als Basis eine [https://www.ikea.com/de/de/p/tertial-arbeitsleuchte-weiss-70355455/ Tertial von Ikea] zugelegt, die seitdem auf dem Dachboden lag. Also warum nicht das Teil zu einem Mikrofonarm umbauen? Das Design ist mit Sketchup schnell hingekritzelt und so gestaltet, dass der Rekorder bzw. der Halter in beide Richtungen (bzw. Seiten des Tisches) montiert werden kann. Damit nicht das ganze Teil in die Tonne wandert, ging zuerst nur die Aufnahme für den Arm über das Druckbett, mit knapp 15 Minuten Druckzeit. Nachdem es gut gepasst hat, ging es in die Vollen: <gallery> Mikrohalter1.jpg | Frisch vom Drucker und sogar noch warum Mikrohalter2.jpg | Mit installiertem Rekorder am Arm </gallery> USB- und Audiokabel sind mit ein paar Kabelbinder befestigt und in "Ruheposition" ist das Teil komplett außerhalb der Arbeitsfläche. mit einem Zug ist das Mikro in perfekter Position und kann sehr einfach neu positioniert werden. Gleichzeitig ist der "Luftraum" darunter komplett frei. Allerdings gibt es einen Nachteil: Die Mikrofonkapseln im Rekorder sind sehr stark mit dem Gehäuse verkoppelt, das Gehäuse ist sehr stark mit dem Arm verkoppelt und der ist wiederum fest am Tisch angeschnallt. Tippen auf der Tastatur geht kaum als Körperschall durch, Trommeln auf dem Tisch oder Klicken des Mausrads hört man schon eher - inklusive Vibrationseffekte der Federn am Arm. Auch kann man an den Federn sehr schön Gitarre spielen. Schaumstoff an der Schraube und zwischen Platte und Rekorder bringen kaum etwas. Abhilfe dürfte eine Mikrofonspinne schaffen, die ich für den H2n bis jetzt noch nicht fertig finden konnte. Heißt also: selber machen. ==Download== * [[Datei:Mikrohalter.zip|Download]] Design aus Sketchup Make 2017 & STL-Datei [[Kategorie:3D-Druck]] [[Kategorie:Raspberry Pi]] [[Kategorie:Pirozeda]] e05bfa660757a0b5dd2a157d4f094635626ee8bb 1494 1492 2020-04-08T20:28:01Z Chris 2 /* Mikrofonarm für den H2n */ wikitext text/x-wiki =Raspberry Pi Zero Spacer= HATs halten auf dem Raspberry Pi zwar über die Stiftleiste schon relativ gut, allerdings ist es doch eine etwas wackelige Angelegenheit. Mit den Buchsen- und Stiftleisten, die ich verwende (die ebenfalls denen von Reichelt entsprechen dürften), ist der Abstand zwischen den Leiterkarten 11 mm. Solche hat Reichelt aktuell leider nicht im Programm. Warum also nicht selber machen? Einfach nur Distanzbolzen zu drucken ist natürlich langweilig - zudem rollen sie schnell vom Tisch und das anbringen ist eher fummelig. Ein Steg wirkt da Wunder. Am schnellsten (und ohne Materialverschwendung) funktioniert das, wenn er direkt auf der Grundplatte aufliegt. Allerdings ist er dann bei einigen HATs im Weg, daher gibt es zwei Versionen, einmal aufliegend und einmal mit 2 mm Abstand zur Unterseite: <gallery> rpizero_spacers.jpg|Beide Versionen des Abstandshalters rpizero_spacer_flat.jpg|Verbauter flacher Abstandshalter rpizero_spacer_lifted.jpg|Verbauter angehobener Abstandshalter </gallery> Als Schrauben dürften sich am besten M2,5x16 eignen. ==Download== * [[Datei:rpizero_spacer.zip|Download]] Design aus Sketchup Make 2017 & STL-Dateien =Diamex AVR-Prog Bodenplatte= Der AVR-Prog ist funktional ein echt schönes Stück Hardware, kommt aber leider komplett ohne Gehäuse. Hat man wie ich einen eher unordentlichen Schreibtisch, ist die Gefahr durch Kurzschlüsse verdammt groß. Deshalb habe ich eine kleine Bodenplatte erstellt, die man auch mit einer M2x6 Senkkopfschraube (bitte nur mit Kunststoffmutter) fixieren kann. <gallery> Backplate_diamex_avr-prog.jpg|AVR-Prog mit angeschnappter Bodenplatte (und gebrochenem Haken) </gallery> Achtung: Die Toleranzen sind sehr eng gewählt, Nacharbeiten können nötig sein. ==Download== * [[Datei:backplate_all-avr.zip|Download]] Design aus Sketchup Make 2017 & STL-Datei =USB-I²C-Bridge Bodenplatte= Ein bisschen mehr Schutz gibt es auch für die [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge|USB-I²C-Bridge]] <gallery> Backplate_mcp_usb_i2c.jpg|Sieht auch transparent schick aus </gallery> Zum Anbringen einfach auf der Seite mit den beiden Schnapphaken einfädeln, die andere Seite mit einem Schraubendreher bisschen aufbiegen und die Leiterkarte eindrücken. Achtung: Die Toleranzen sind sehr eng gewählt, Nacharbeiten können nötig sein. ==Download== * [[Datei:backplate_mcp_i2c_v1.zip|Download]] Design aus FreeCAD 0.18 (nicht voll parametrisch!) & STL-Datei =Mikrofonarm für den Zoom H2n= Aufgrund der Pandemie 2020 (deren Namen ich nicht nennen möchte) sitze ich schon eine Weile im Homeoffice. Da die ganzen Meetings nun online stattfinden, brauche ich Mikrofon und Kopfhörer. Da mein Bluetooth-Headset auf lausige Telefonqualität abfällt, verwende ich meinen treuen Zoom H2n als Mikrofon und Kopfhörer-DAC. Die ersten Zwei Wochen stand es auf einem kleinen Dreibein bzw. einem Gorilla Pod zwischen Mund und Tastatur. Etwas umständlich, wenn man während der Telkos tippen will/muss und man muss jedes Mal nach unten greifen, wenn spontan jemand anruft. Für einen Versuch, eine Arbeitsleuchte selbst zu bauen, habe ich mir vor einiger Zeit als Basis eine [https://www.ikea.com/de/de/p/tertial-arbeitsleuchte-weiss-70355455/ Tertial von Ikea] zugelegt, die seitdem auf dem Dachboden lag. Also warum nicht das Teil zu einem Mikrofonarm umbauen? Das Design ist mit Sketchup schnell hingekritzelt und so gestaltet, dass der Rekorder bzw. der Halter in beide Richtungen (bzw. Seiten des Tisches) montiert werden kann. Damit nicht das ganze Teil in die Tonne wandert, ging zuerst nur die Aufnahme für den Arm über das Druckbett, mit knapp 15 Minuten Druckzeit. Nachdem es gut gepasst hat, ging es in die Vollen: <gallery> Mikrohalter1.jpg | Frisch vom Drucker und sogar noch warum Mikrohalter2.jpg | Mit installiertem Rekorder am Arm </gallery> USB- und Audiokabel sind mit ein paar Kabelbinder befestigt und in "Ruheposition" ist das Teil komplett außerhalb der Arbeitsfläche. mit einem Zug ist das Mikro in perfekter Position und kann sehr einfach neu positioniert werden. Gleichzeitig ist der "Luftraum" darunter komplett frei. Allerdings gibt es einen Nachteil: Die Mikrofonkapseln im Rekorder sind sehr stark mit dem Gehäuse verkoppelt, das Gehäuse ist sehr stark mit dem Arm verkoppelt und der ist wiederum fest am Tisch angeschnallt. Tippen auf der Tastatur geht kaum als Körperschall durch, Trommeln auf dem Tisch oder Klicken des Mausrads hört man schon eher - inklusive Vibrationseffekte der Federn am Arm. Auch kann man an den Federn sehr schön Gitarre spielen. Schaumstoff an der Schraube und zwischen Platte und Rekorder bringen kaum etwas. Abhilfe dürfte eine Mikrofonspinne schaffen, die ich für den H2n bis jetzt noch nicht fertig finden konnte. Heißt also: selber machen. ==Download== * [[Datei:Mikrohalter.zip|Download]] Design aus Sketchup Make 2017 & STL-Datei [[Kategorie:3D-Druck]] [[Kategorie:Raspberry Pi]] [[Kategorie:Pirozeda]] 0bd3db1902e46cde14279fe86498b7a5303b3d25 1496 1494 2020-04-08T20:33:58Z Chris 2 /* Mikrofonarm für den Zoom H2n */ wikitext text/x-wiki =Raspberry Pi Zero Spacer= HATs halten auf dem Raspberry Pi zwar über die Stiftleiste schon relativ gut, allerdings ist es doch eine etwas wackelige Angelegenheit. Mit den Buchsen- und Stiftleisten, die ich verwende (die ebenfalls denen von Reichelt entsprechen dürften), ist der Abstand zwischen den Leiterkarten 11 mm. Solche hat Reichelt aktuell leider nicht im Programm. Warum also nicht selber machen? Einfach nur Distanzbolzen zu drucken ist natürlich langweilig - zudem rollen sie schnell vom Tisch und das anbringen ist eher fummelig. Ein Steg wirkt da Wunder. Am schnellsten (und ohne Materialverschwendung) funktioniert das, wenn er direkt auf der Grundplatte aufliegt. Allerdings ist er dann bei einigen HATs im Weg, daher gibt es zwei Versionen, einmal aufliegend und einmal mit 2 mm Abstand zur Unterseite: <gallery> rpizero_spacers.jpg|Beide Versionen des Abstandshalters rpizero_spacer_flat.jpg|Verbauter flacher Abstandshalter rpizero_spacer_lifted.jpg|Verbauter angehobener Abstandshalter </gallery> Als Schrauben dürften sich am besten M2,5x16 eignen. ==Download== * [[Datei:rpizero_spacer.zip|Download]] Design aus Sketchup Make 2017 & STL-Dateien =Diamex AVR-Prog Bodenplatte= Der AVR-Prog ist funktional ein echt schönes Stück Hardware, kommt aber leider komplett ohne Gehäuse. Hat man wie ich einen eher unordentlichen Schreibtisch, ist die Gefahr durch Kurzschlüsse verdammt groß. Deshalb habe ich eine kleine Bodenplatte erstellt, die man auch mit einer M2x6 Senkkopfschraube (bitte nur mit Kunststoffmutter) fixieren kann. <gallery> Backplate_diamex_avr-prog.jpg|AVR-Prog mit angeschnappter Bodenplatte (und gebrochenem Haken) </gallery> Achtung: Die Toleranzen sind sehr eng gewählt, Nacharbeiten können nötig sein. ==Download== * [[Datei:backplate_all-avr.zip|Download]] Design aus Sketchup Make 2017 & STL-Datei =USB-I²C-Bridge Bodenplatte= Ein bisschen mehr Schutz gibt es auch für die [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge|USB-I²C-Bridge]] <gallery> Backplate_mcp_usb_i2c.jpg|Sieht auch transparent schick aus </gallery> Zum Anbringen einfach auf der Seite mit den beiden Schnapphaken einfädeln, die andere Seite mit einem Schraubendreher bisschen aufbiegen und die Leiterkarte eindrücken. Achtung: Die Toleranzen sind sehr eng gewählt, Nacharbeiten können nötig sein. ==Download== * [[Datei:backplate_mcp_i2c_v1.zip|Download]] Design aus FreeCAD 0.18 (nicht voll parametrisch!) & STL-Datei =Mikrofonarm für den Zoom H2n= Aufgrund der Pandemie 2020 (deren Namen ich nicht nennen möchte) sitze ich schon eine Weile im Homeoffice. Da die ganzen Meetings nun online stattfinden, brauche ich Mikrofon und Kopfhörer. Da mein Bluetooth-Headset auf lausige Telefonqualität abfällt, verwende ich meinen treuen Zoom H2n als Mikrofon und Kopfhörer-DAC. Die ersten Zwei Wochen stand es auf einem kleinen Dreibein bzw. einem Gorilla Pod zwischen Mund und Tastatur. Etwas umständlich, wenn man während der Telkos tippen will/muss und man muss jedes Mal nach unten greifen, wenn spontan jemand anruft. Für einen Versuch, eine Arbeitsleuchte selbst zu bauen, habe ich mir vor einiger Zeit als Basis eine [https://www.ikea.com/de/de/p/tertial-arbeitsleuchte-weiss-70355455/ Tertial von Ikea] zugelegt, die seitdem auf dem Dachboden lag. Also warum nicht das Teil zu einem Mikrofonarm umbauen? Das Design ist mit Sketchup schnell hingekritzelt und so gestaltet, dass der Rekorder bzw. der Halter in beide Richtungen (bzw. Seiten des Tisches) montiert werden kann. Damit nicht das ganze Teil in die Tonne wandert, ging zuerst nur die Aufnahme für den Arm über das Druckbett, mit knapp 15 Minuten Druckzeit. Nachdem es gut gepasst hat, ging es in die Vollen: <gallery> Mikrohalter1.jpg | Frisch vom Drucker und sogar noch warum Mikrohalter2.jpg | Mit installiertem Rekorder am Arm </gallery> USB- und Audiokabel sind mit ein paar Kabelbinder befestigt und in "Ruheposition" ist das Teil komplett außerhalb der Arbeitsfläche. mit einem Zug ist das Mikro in perfekter Position und kann sehr einfach neu positioniert werden. Gleichzeitig ist der "Luftraum" darunter komplett frei. Allerdings gibt es einen Nachteil: Die Mikrofonkapseln im Rekorder sind sehr stark mit dem Gehäuse verkoppelt, das Gehäuse ist sehr stark mit dem Arm verkoppelt und der ist wiederum fest am Tisch angeschnallt. Tippen auf der Tastatur geht kaum als Körperschall durch, Trommeln auf dem Tisch oder Klicken des Mausrads hört man schon eher - inklusive Vibrationseffekte der Federn am Arm. Auch kann man an den Federn sehr schön Gitarre spielen. Schaumstoff an der Schraube und zwischen Platte und Rekorder bringen kaum etwas. Abhilfe dürfte eine Mikrofonspinne schaffen, die ich für den H2n bis jetzt noch nicht fertig finden konnte. Heißt also: selber machen. Auch ist das Teil bei IIRC 30 % Infill & aktiviertem Gradient und mit PLA gedruckt nicht sehr steif. Bei der Montage rechts am Tisch könnte die Platte deutlich kürzer sein (weil die Stecker keinen Platz brauchen), was der Stabilität deutlich zugutekommen würde. ==Download== * [[Datei:Mikrohalter.zip|Download]] Design aus Sketchup Make 2017 & STL-Datei [[Kategorie:3D-Druck]] [[Kategorie:Raspberry Pi]] [[Kategorie:Pirozeda]] 57ae8d6a1cfcc6a20527036d4a26b5a05eb8c9a3 USB-Fußtaster 0 623 1539 1431 2020-04-09T19:54:10Z Chris 2 /* Modus 2: Makro-Tastatur */ </code> vergessen wikitext text/x-wiki [[Datei:Footswitch.jpg|thumb|Fertig aufgebauter Fußtaster]] "Schau Mama, freihändig!" Wer kennt das nicht? Man muss auf mehreren Leiterkarten verschiedene Spannungen messen. Üblicherweise läuft es dann wie folgt ab: # Messspitzen platzieren # Wert vom Messgerät ablesen # Messspitzen ablegen und zum PC umdrehen # Messwert eintippen # Zurückdrehen, Messspitzen wieder in die Hände nehmen # Nochmal nachschauen, welcher Messpunkt jetzt dran ist # Wiederholen Ab und zu mischt sich dann das erneute Messen ein, weil ein Wert unplausibel ist und man entweder einen Zahlendreher drin oder schneller getippt als gedacht hat. Unterm Strich ist es auf jeden Fall sehr zeitraubend und nervig. Gleichzeitig baumeln die Füße unbeteiligt am Stuhl herunter. Die meisten Messgeräte (und anderes Laborequipment) lassen sich über den PC kontrollieren, warum also nicht gleich die richtigen Werte z. B. nach Excel transferieren? Nur irgendwie muss man den Prozess anstoßen... =Die schnelle Lösung= Tastatur ist blöd, also muss eine andere Eingabemöglichkeit her. Ein Taster und eine Projektbox ist schnell gefunden, Loch in die Box und ein paar große Schrauben dazu (damit sie nicht gleich abhaut) und fertig ist der improvisierte Fußtaster. Nur wie kommt die Info in den PC? Die serielle Schnittstelle hat neben Rx und Tx oft auch Steuerleitungen – aus den alten Tagen, in denen Modems noch so richtig langsam waren. Diese lassen sich in so ziemlich jeder Programmiersprache kontrollieren und abfragen. Ein FT232 liegt auch noch herum, also Taster angelötet und los geht’s! Das Programm ist in Python geschrieben, pollt die CTS-Leitung und sobald diese low wird, wird per pyVisa den Multimeter der aktuelle Messwert entlockt, passend formatiert und mit dem Keyboard-Modul "ausgetippt". Damit die Augen am Mikroskop bleiben können, wird zudem ein kurzer Piepton ausgegeben. Sehr viel Spaß für wenig Geld. Leider muss man bei jeder Benutzung schauen, welcher COM-Port dem Adapter zugeordnet wurde und ob dieser auch wirklich im Script steht. =Die schöne Lösung= Eines Tages brachte mein Kollege einen kleinen Pappkarton vom [https://www.pollin.de Ramschmax] mit, Inhalt: [https://www.pollin.de/p/fusstaster-pfs-135a-10-a-250-v-420705 420705]. Ein Gusseiserner Fußtaster mit schönem Klick-Klack-Mikroschalter. Der hat etwas Besseres als den schnöden UART-Adapter mit Zwillingslitze verdient – endlich wieder eine schöne Anwendung für [https://www.obdev.at/vusb/ V-USB]! Was soll das Teil können? Am besten natürlich so viel wie möglich, damit es vielleicht sogar als "Adaptive Controller" dienen kann. Deshalb habe ich mich dafür entschieden, einen Multidevice-Ansatz zu fahren. Das umfasst aktuell: * Generisches USB-HID * Einzeltasten-Tastatur * Makro-Tastatur * Joystick =Hardware= Die Hardware könnte nicht einfacher sein - sie entspricht größtenteils dem [https://www.obdev.at/products/vusb/easylogger.html Easylogger]-Beispielprojekt, nur dass anstelle der automatischen Oszillator-Kalibrierung ein externer Quarz verwendet wird. Hintergrund hierfür ist, dass das [[SNES-Joypad]], das sich selbst kalibriert (oder zumindest sollte), am RetroPie beim Booten oft nicht erkannt wird. Kann aber auch gut sein, dass es sich um einen Bug in meiner Firmware handelt. Die Bauteile sind - abgesehen vom Quarz und Mikrocontroller in SMD-Bauform. Als MCU werkelt fürs Erste ein ATtiny85, der später noch herunterskaliert werden kann. Die Wahl auf das DIP-Gehäuse fiel, um ohne Löten die Firmware herunterzuladen. Mit Quarz als Taktquelle bleibt noch ein "richtiger" IO übrig (sofern man den Reset-Pin nicht deaktiviert) - mehr braucht man nicht. Eine eigens designte Leiterkarte ist aufgrund der Einfachheit der Schaltung völlig unnötig, aber es war noch Platz auf dem Panel... <gallery> footswitch 1.0 sch.png|Schaltplan footswitch 1.0 top.png|Bestückungsplan Oberseite footswitch 1.0 bot.png|Bestückungsplan Unterseite footswitch 1.0 assy.jpg|Aufgebaute Leiterkarte </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || MA03-1 || |- | 1 || SV1 || || MA04-1 || GC 2212-EU030 |- | 1 || C1 || 100n || C0603 || X7R-G0603 100N |- | 1 || C4 || 10u || C0805 || KEM X7R0805 10U |- | 1 || Q1 || 12M || HC49U-V || 12,0000-HC49U-S |- | 1 || R11 || 150 || R0603 || RND 0603 1 150 |- | 1 || C5 || 150n || C0603 || X7R 0603FCE 150N |- | 2 || C2, C3 || 22p || C0603 || RND 150MT18N2202 |- | 1 || R3 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || R10 || 4k7 || R0603 || RND 0603 1 4,7k |- | 2 || R1, R2 || 68 || R0603 || RND 0603 1 68 |- | 1 || IC1 || ATTINY 85-20 PU || DIL08 || ATTINY 85-20 PU |- | 2 || D1, D2 || BZX84C3V6 || SOT23 || SMD ZD 3,6 |} Leider stellte sich erst zu spät heraus, dass die Leiterkarte ein bisschen zu groß ist, um sie an der eigentlich vorgesehenen Stelle zu montieren. Man kann sie zwar ein bisschen schräg anschrauben und von der Ecke noch etwas Material wegnehmen, aber dann ist die USB-Leitung auch wieder im Weg. Das Design ist also nicht so richtig geglückt... Aber kein Problem, dass man nicht mit ein bisschen Schrumpfschlauch lösen könnte: <gallery> footswitch 1.0 designflaw 1.jpg|Dort sollte die Leiterkarte hin footswitch 1.0 designflaw 2.jpg|...und hier ist sie footswitch 1.0 designflaw 3.jpg|weitere Perspektive </gallery> Der Schirm ist übrigens auf ein Stück Leitung gecrimpt, das wiederum an die Halterung des Tasters gelötet ist. =Firmware= ==Firmware== {{Infobox AVR | Typ = ATtiny85 | Takt = 12 | FuseH = D7 | FuseL = DE | FuseE = FF }} Die Firmware ist mehr oder weniger viergeteilt, entsprechend den verschiedenen Modi. Hierfür gibt es mehrere Gründe: * die freien VID/PID-Paare sind auf die verschiedenen Funktionen beschränkt und es lässt sich nicht zweifelsfrei sagen, ob Multi-Endpoint-Konfigurationen erlaubt sind * Die Fragmentierung macht den Code (teilweise) einfacher und übersichtlicher * Keinerlei Treiberprobleme (es gibt wohl Betriebssysteme, die sich an Multi-Endpoint verschlucken) * Es ist nicht ganz so üblich und in der Implementierung interessanter Nach dem Reset liest die Firmware den zu verwendenden Modus aus dem EEPROM. Ist diese ungültig oder der IO des Tasters auf Masse gezogen, wird der auf Generisches HID gesetzt. Gegenüber des USB-Treibers wird nun auch der Pointer für die USB-Deskriptoren gesetzt (die sich wiederum im Flash befinden). Anschließend läuft die Initialisierung der unterschiedlichen Modi und es wird in die entsprechende Endlosschleife gesprungen. Als USB VID/PID-Paare werden von obdev frei zur Verfügung gestellten verwendet: * HID: 0x16C0/0x27D9 * Tastatur: 0x16C0/0x27DB * Gamepad: 0x16C0/0x27DC Im Grunde ist das alles kein Hexenwerk, allerdings haben die "Dynamisierung" der USB-Deskriptoren einiges an (auf dem Attiny schwierige) Fehlersuche gekostet. Über Manche Dinge, wie z. B. wie man die verschiedenen Deskriptoren den Anfragen zuordnet, ist die Dokumentation leider etwas vage (oder ich habe sie nicht richtig gelesen/falsch gesucht). Auch lässt sich die Firmware noch ziemlich optimieren, das gesteckte Ziel wäre, dass sie auf den ATtiny45 passt. Aktuell ist hauptsächlich die RAM-Belegung ein Problem (und noch nicht optimal). =Konfiguration= Um die Konfiguration des Fußtasters ändern zu können, muss er sich in Modus 2 (Generisches HID) befinden. Sollte dieser Modus nicht aktiv sein, kann er erreicht werden indem der Taster gedrückt wird, während der USB-Stecker verbunden wird. In den Report-Beispielen werden stets hexadezimale Zahlen verwendet. Angaben mit <code>xx</code> sind beliebig bzw. müssen ignoriert werden. ==Keycodes== Bevor auf die verschiedenen Funktionen im Detail eingegangen wird, ein paar Worte zu den Keycodes: Tastaturen sind seit jeher ziemlich einfach gestrickt. So "weiß" der Controller der Tastatur zwar an welcher Position eine Taste gedrückt wird, aber nicht welches Layout sie vertritt - dies wird erst durch das Betriebssystem umgesetzt. Das hat zum Beispiel den Effekt, dass mit einer deutschen Tastatur an einem auf Englisch eingestellten PC u. a. Y und Z vertauscht sind (und man beim Raspberrz Pi das Passwort mindestens einmal falsch eingibt). Diese Eigenschaft betrifft natürlich auch den Fußtaster. Die Keycodes für englische Tastaturen können in der Spezifikation [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 "Universal Serial Bus HID Usage Tables"] in der aktuellen Version ab Seite 53 (Kapitel 10 Keyboard/Keypad Page (0x07)]) nachgeschlagen werden. Für das deutsche Layout befindet sich eine Tabelle im Download-Bereich (keine Garantie auf Vollständigkeit und Korrektheit). ==Modus 0: Generisches HID== Die Kommunikation findet über Report ID 0 mit 8 Datenbytes statt. Beim Senden von Reports definiert das erste Byte den Befehl, in den weiteren befinden sich die Parameter dessen: {| class="wikitable" ! Nummer || Befehl || Beschreibung |- | 0 || NOP || Keine Operation, dieser Code wird bei den Antworten für den Status des Tasters verwendet |- | 1 || Restart || Neustart des Mikrocontrollers (ersetzt das Aus- und Einstecken nachdem der Modus umgestellt wurde) |- | 2 || Lesen Modus || Gibt den Interface-Modus zurück |- | 3 || Setzen Modus || Setzt den Interface-Modus |- | 4 || Lesen Einzeltaste || Gibt den Keycode der Einzeltasten-Tastatur zurück |- | 5 || Setzen Einzeltaste || Setzt den Keycode der Einzeltasten-Tastatur |- | 6 || Lesen Tastensequenz || Gibt 6 Byte der Sequenz des angegebenen Blocks (in Byte 1) zurück |- | 7 || Setzen Tastensequenz || Setzt die 6 Bytes der Sequenz des angegebenen Blocks (in Byte 1) |} Jeder Befehl wird beantwortet, wobei dem ersten Byte eine Statusinformation mit bitweise Oder hinzugefügt wird: {| class="wikitable" ! Nummer || Status || Beschreibung |- | 0x00 || None || Wird nicht verwendet |- | 0x40 || Busy || Der Befehl wurde nicht ausgeführt, weil der Controller beschäftigt ist |- | 0x80 || Ok || Der Befehl wurde erfolgreich ausgeführt, die optionale Antwort befindet sich in den restlichen Bytes |- | 0xC0 || Error || Beim Ausführen des Befehls ist ein Fehler aufgetreten |} ===Tastenstatus=== Für jede Änderung des Tastenstatus wird ein Report übertragen: <code>&lt; <span class="hb1">00</span> <span class="hb2">BB</span> xx xx xx xx xx xx</code> * <span class="hb1">"Befehl": Status der Taste</span> * <span class="hb2">Status der Taste - 0: nicht gedrückt, 1: gedrückt</span> ==Modus 1: Einzeltasten-Tastatur== In diesem Modus verhält sich der Fußtaster wie die Taste einer Tastatur. Die zu drückende Taste kann über Modus 2 festgelegt werden. Leider ist es aktuell noch nicht möglich, Multimedia-Tasten (Wiedergabesteuerung, Lautstärke, Anwendungssteuerung) zu verwenden. ===Lesen=== Zum Zurücklesen der verwendeten Taste muss folgender Report gesendet werden: <code>&gt; <span class="hb1">04</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste</span> Die Antwort entspricht folgendem Muster: <code>&lt; <span class="hb1">84</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste (OK)</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) ** 0x01: Steuerung links ** 0x02: Umschalttaste links ** 0x04: Alt links ** 0x08: GUI links (u. a. Windows-Taste) ** 0x10: Steuerung rechts ** 0x20: Umschalttaste rechts ** 0x40: Alt rechts (müsste Alt+Gr sein) ** 0x80: GUI rechts (müsste Kontextmenü sein) * <span class="hb3">Keycode Taste</span> ===Schreiben=== Zum Setzen einer Taste folgender Report gesendet werden: <code>&gt; <span class="hb1">05</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Setzen Einzeltaste</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) * <span class="hb3">Keycode Taste</span> Die restlichen Bytes im Report werden ignoriert. Die Bestätigung wird wie unter "Modus 2" beschrieben gesendet. Da keine Readback stattfindet, wird immer mit "OK" geantwortet: <code>&lt; <span class="hb1">85</span> xx xx xx xx xx xx xx</code> ==Modus 2: Makro-Tastatur== Über die Makro-Tastatur können längere Tastenfolgen ausgegeben werden. Für diesen Zweck sind 128 Byte im EEPROM vorgesehen, was einer maximalen Folge von etwa 63 Anschlägen entspricht. Aktuell kann nur eine Taste gleichzeitig gedrückt werden kann - ein Rollover ist dementsprechend nicht möglich. Die Ausgabe erfolgt mit maximaler Geschwindigkeit, also mit etwa 100 Anschlägen pro Sekunde, wobei zwischen gleichlautenden Anschlägen sowie nach dem letzten Zeichen automatisch ein Loslassen der Taste eingefügt wird, was zu einer kleinen Verzögerung führt und damit das Timing verändert Beispiel: Bei der Ausgabe des Wortes <code>Hallo</code> folgende Reports übertragen: * Umschalttaste drücken, Taste "H" drücken * Umschalttaste loslassen, Taste "A" drücken * Taste "L" drücken * Taste "L" loslassen * Taste "L" drücken * Taste "O" drücken * Taste "O" loslassen So dauert die Übertragung des Wortes - bei einem Report-Intervall von 10 ms - etwa 70 ms statt den zunächst anzunehmenden 50 ms. ===Datenformat=== Die Daten werden im Muster <code>Befehl + Daten</code> gespeichert, wobei die Datenlänge dynamisch (aber anhand des Befehls ersichtlich) ist. Dementsprechend sind die Befehle teilweise als Flags aufgebaut, zum besseren Verständnis hier im Binärformat: * <code>0b<b>11111111</b></code>: Ende der Sequenz (entspricht nicht beschriebenen Speicherzellen), keine Daten * <code>0b<b>1</b><span class="hb1">ppppppp</span></code>: Pause in 5 ms-Schritten, p = 0 ... 126, t = (p + 1) * 5 ms, maximal 635 ms, keine Daten * <code>0b<b>0</b><span class="hb2">mm</span><span class="hb3">xx</span>xxx</code>: Verhalten der Modifier ** <code><span class="hb2">0b00</span></code>: Modifier beibehalten, keine Daten ** <code><span class="hb2">0b01</span></code>: Modifier für nachfolgende Taste drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb2">0b10</span></code>: Modifier dauerhaft halten, +1 Byte Daten ** <code><span class="hb2">0b11</span></code>: Modifier loslassen, keine Daten * <code>0b<b>0</b><span class="hb2">xx</span><span class="hb3">kk</span>xxx</code>: Verhalten der Taste ** <code><span class="hb3">0b00</span></code>: Taste beibehalten, keine Daten ** <code><span class="hb3">0b01</span></code>: Taste einmal drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb3">0b10</span></code>: Taste dauerhaft halten (bis eine andere Taste gedrückt wird), +1 Byte Daten ** <code><span class="hb3">0b11</span></code>: Taste loslassen, keine Daten Sollen Modifier und Taste mit einem Befehl verändert werden, wird zuerst der Modifier erwartet, dann die Taste: <code>0b0<span class="hb2">10</span><span class="hb3">01</span>000 <span class="hb4">0b00000010</span> <span class="hb5">0b00001011</span></code> <span class="hb2">Drückt und hält</span> die <span class="hb4">linke Umschalttaste</span> und drückt die <span class="hb5">Taste H (0x0B)</span> <span class="hb3">einmal</span>. Beispiel: Es soll die Zeichenfolge <code>Hallo WELT</code> mit anschließendem Zeilenumbruch ausgegeben werden, mit einer Pause von 500 ms nach "Hallo". Die Sequenz sieht nun wie folgt aus (Binär und Hex gemischt, Hex für Keycodes): {| class="wikitable" ! Code || Befehl || Parameter |- | <code>0b0<span class="hb1">01</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x0B</span></code> || <span class="hb1">Modifier einmal drücken</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Linke Umschalttaste</span>, <span class="hb4">Taste H</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x04</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste A</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x12</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste O</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1100011</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Pause mit 99 Zeiteinheiten</span>: t = (99 + 1) * 5 ms = 500 ms |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb3">0x2C</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Leertaste</span> |- | <code>0b0<span class="hb1">11</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x1A</span></code> || <span class="hb1">Modifier drücken und halten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Rechte Umschalttaste</span>, <span class="hb4">Taste W</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x08</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste E</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x17</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste T</span> |- | <code>0b0<span class="hb1">10</span><span class="hb2">00</span>000</code> || <span class="hb1">Modifier loslassen</span>, <span class="hb2">Kein Tastendruck</span> || - |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x28</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Return-Taste</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1111111</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Ende der der Sequenz</span> |} ===Lesen=== Wie bereits in der Befehlsübersicht erwähnt, erfolgt das Lesen und Schreiben der Sequenzdaten in Blöcken: <code>&gt; <span class="hb1">06</span> <span class="hb2">CC</span> xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> Als Antwort bekommt man dann die Daten des jeweiligen Blocks: <code>&lt; <span class="hb1">86</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Lesen Sequenz (OK)</span> * <span class="hb2">Blocknummer: 0 ... 21 </span> * <span class="hb2">6 Datenbytes des Blocks</span> Ist der letzte Block nicht "füllend", sind die restlichen Bytes zufällig, ebenso kann über das "End of Sequence" hinaus gelesen werden. ===Schreiben=== Das Schreiben von Blöcken ist der Antwort vom Lesen sehr ähnlich: <code>&gt; <span class="hb1">07</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Schreiben Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> * <span class="hb2">6 Datenbytes des Blocks</span> Sobald die Daten geschrieben wurden, antwortet der Mikrocontroller mit: <code>&lt; <span class="hb1">06</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Schreiben Sequenz (OK)</span> ==Modus 3: Gamepad== Es ist keine Konfiguration notwendig, das Gamepad meldet sich mit einer Taste und kann in Anwendungen wie gewohnt zugeordnet werden. <gallery> footswitch_gamepad.png|Eigenschaftenseite in Windows </gallery> Leider erkennt weder Firefox 73 noch Chromium 82 das Pad im html5gamepad-Tester. Anzumerken ist, dass wie bei der Einzeltasten-Tastatur Reports nur bei Zustandsänderung der Taste gesendet werden. Bis jetzt konnte ich dadurch keine Einschränkungen feststellen. =PC-Software= Aktuell gibt es eine kleine Python-Lib und ein paar Beispiele dazu. Siehe Downloads. =Anmerkungen= * Die Firmware auf dem Tiny85 zu entwickeln war grauenvoll, da man nur sehr schlecht debuggen kann. Das nächste Mal lieber auf einem Mikrocontroller mit deutlich mehr IOs und Hardware-UART entwickeln und anschließend auf ein kleineres Geschwister portieren * [https://github.com/micronucleus/micronucleus/ micronucleus] ist ein USB-Bootloader basierend auf V-USB, den ich bis jetzt noch nicht verwendet habe, in Zukunft aber sollte * Der Quellcode steht, wie von objective development gefordert, unter GPLv2 =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= * [[Datei:Footswitch.zip]] Schaltplan & Layout in EAGLE 7.7.0, Firmware & Sourcen in Atmel Studio 7, Beispielanwendung in Python 3.7 =Weblinks= * [https://www.uwe-sieber.de/usbtreeview.html USB Device Tree Viewer] zeigt sehr detaillierte Infos zu angeschlossenen USB-Geräten an * [http://wireshark.org/ Wireshark] kann auch USB tracen * [https://eleccelerator.com/usbdescreqparser/ USB Descriptor and Request Parser] * [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 Universal Serial Bus HID Usage Tables, Seite 53: 10 Keyboard/Keypad Page (0x07)] [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:Kleine Helferlein]] 0e58ccee30efdba01261aeed34183ec62abd87d9 Benutzer:Chris 2 45 1540 1396 2020-04-09T20:17:03Z Chris 2 wikitext text/x-wiki = Wie es dazu kam = Irgendwann um die Jahrtausendwende (Ende 2002) fing ich damit an, meine (mehr oder weniger gelungenen) Bastel-Projekte in HTML zu verwandeln und auf hobby-elektronik.de.vu zu veröffentlichen. Der Speicherplatz bei Tripod wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich ein knappes Jahr später - am 20.12.2003 - auf das damals schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10.04.2005 die Domain hobbyelektronik.org registriert. Zu .org kam es, da jemand eine Woche davor die .net-Domain weggeschnappte. Im Nachhinein bin ich um diesen Umstand sehr glücklich. Eine Organisation im eigentlichen Sinne ist die Website zwar nicht, entspricht aber (hoffentlich) dem Charakter, dem .org nachgesagt wird ;) = Was ich mache = Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" bezeichnen. Von Oktober 2009 bis Juli 2013 habe ich Elektrotechnik/Nachrichtentechnik an der [http://www.hs-ulm.de Hochschule Ulm] studiert und arbeite seit Oktober 2013 in der Automobil-Branche. Die Schnittmenge bzw. vielmehr die Verbindung aus den beiden Bereichen kommen auch wieder in meinen Hobbys zusammen. = Warum das Ganze? = Ganz einfach: Weil es mir Spaß macht. Wie an anderer Stelle schon erwähnt, bezeichne ich diese Seite als "nicht-kommerzielles Umfeld". Damit ist gemeint, dass ich mit dieser Homepage kein Geld verdiene (keine Werbung, keine Partnerschaften mir irgendwelchen Firmen, etc.) und es ehrlich gesagt auch nicht will. Das bedeutet auch, dass Produkterwähnungen und evtl. auch Empfehlungen aus meiner eigenen Erfahrung und Meinung gemacht werden. (Wer spenden will - gerne auch Sachspenden - ist natürlich willkommen ;)). Neben dem Spaß geht es mir auch darum, etwas an andere Bastler, Elektronik-Einsteiger und DICH weiter- bzw. zurückzugeben. Auch ich habe mal sehr klein angefangen und war froh um alles, was mich näher in Richtung Computer und Elektronik brachte (und auch heute noch bringt). Wenn man so will, kann man es als Kreislauf verstehen :) [http://sprut.de/misc/hpphilos.htm Sprut] hat es meiner Meinung mit seiner Homepage-Philosophie sehr gut getroffen. = Kannst du mir... = ...bei <Thema hier einsetzen> helfen? Jein. Wenn du ehrliches Interesse hast, helfe ich gerne. Was ich allerdings überhaupt nicht ab kann ist die "Mach mal"- bzw. "Freibiermentalität", die manche an den Tag legen. Solche "Anfragen" lasse ich liegen. = Kontakt = Solltest du Fragen, Kritik, Verbesserungsvorschläge oder Fehler auf den Seiten hier gefunden haben - eine kleine Mail genügt und wird gerne beantwortet: chris at hobbyelektronik punkt org Wer mich in sozialen Netzwerken sucht, wird wenig Erfolg haben. Will ich nicht, mach ich nicht. (siehe auch [[Hobbyelektronik.org:Impressum|Impressum]]) 0b40c2bc12ae9e0a738c9a0d3284b665164d9a8f 1541 1540 2020-04-09T20:36:03Z Chris 2 wikitext text/x-wiki = Wie es dazu kam = Irgendwann um die Jahrtausendwende (Ende 2002) fing ich damit an, meine (mehr oder weniger gelungenen) Bastel-Projekte in HTML zu verwandeln und auf hobby-elektronik.de.vu zu veröffentlichen. Der Speicherplatz bei Tripod wurde im Gegensatz zur Werbung nicht mehr und so beschloss ich ein knappes Jahr später - am 20.12.2003 - auf das damals schöne Angebot von Cybton umzusteigen. Nachdem der Webspace dort immer unzuverlässiger wurde und ich endlich einmal eine eigene Domain wollte, wurde - kurz nach meinem 18. Geburtstag - am 10.04.2005 die Domain hobbyelektronik.org registriert. Zu .org kam es, da jemand eine Woche davor die .net-Domain weggeschnappte. Im Nachhinein bin ich um diesen Umstand sehr glücklich. Eine Organisation im eigentlichen Sinne ist die Website zwar nicht, entspricht aber (hoffentlich) dem Charakter, dem .org nachgesagt wird ;) Im November 2007 wurde die Seite auf MediaWiki umgestellt (die alte Seite war noch verfügbar), die meisten Artikel nach und nach umgezogen. Der Blog kam am 18.05.2008 dazu. Zum 15. Geburtstag am 10.04.2020 gab es einen sanften Tapetenwechsel: Das MediaWiki-Skin Vector wurde durch Timeless abgelöst. = Was ich mache = Ich bin ausgebildeter und staatlich geprüfter FIAE und darf mich als "bundesbester IHK-Prüfling im Beruf Fachinformatiker/Anwendungsentwicklung 2008" bezeichnen. Von Oktober 2009 bis Juli 2013 habe ich Elektrotechnik/Nachrichtentechnik an der [http://www.hs-ulm.de Hochschule Ulm] studiert und arbeite seit Oktober 2013 in der Automobil-Branche. Die Schnittmenge bzw. vielmehr die Verbindung aus den beiden Bereichen kommen auch wieder in meinen Hobbys zusammen. = Warum das Ganze? = Ganz einfach: Weil es mir Spaß macht. Wie an anderer Stelle schon erwähnt, bezeichne ich diese Seite als "nicht-kommerzielles Umfeld". Damit ist gemeint, dass ich mit dieser Homepage kein Geld verdiene (keine Werbung, keine Partnerschaften mir irgendwelchen Firmen, etc.) und es ehrlich gesagt auch nicht will. Das bedeutet auch, dass Produkterwähnungen und evtl. auch Empfehlungen aus meiner eigenen Erfahrung und Meinung gemacht werden. (Wer spenden will - gerne auch Sachspenden - ist natürlich willkommen ;)). Neben dem Spaß geht es mir auch darum, etwas an andere Bastler, Elektronik-Einsteiger und DICH weiter- bzw. zurückzugeben. Auch ich habe mal sehr klein angefangen und war froh um alles, was mich näher in Richtung Computer und Elektronik brachte (und auch heute noch bringt). Wenn man so will, kann man es als Kreislauf verstehen :) [http://sprut.de/misc/hpphilos.htm Sprut] hat es meiner Meinung mit seiner Homepage-Philosophie sehr gut getroffen. = Kannst du mir... = ...bei <Thema hier einsetzen> helfen? Jein. Wenn du ehrliches Interesse hast, helfe ich gerne. Was ich allerdings überhaupt nicht ab kann ist die "Mach mal"- bzw. "Freibiermentalität", die manche an den Tag legen. Solche "Anfragen" lasse ich liegen. = Kontakt = Solltest du Fragen, Kritik, Verbesserungsvorschläge oder Fehler auf den Seiten hier gefunden haben - eine kleine Mail genügt und wird gerne beantwortet: chris at hobbyelektronik punkt org Wer mich in sozialen Netzwerken sucht, wird wenig Erfolg haben. Will ich nicht, mach ich nicht. (siehe auch [[Hobbyelektronik.org:Impressum|Impressum]]) 65f2e177eee707a1b4e8500729f0b14b8f0332e7 Hauptseite 0 1 1542 1495 2020-04-10T10:53:46Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <ul id="mw-latest-changes10"> *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] </ul> 38b4a0d0aacaedf0ef455994bcb93526edd0ab59 1543 1542 2020-04-10T10:55:08Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] </div> 328500deef99bbaec70b53eb7309f1077c0d350a 1544 1543 2020-04-10T10:59:17Z Chris 2 /* Neues & Änderungen */ Vollständige Historie wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] </div> 0c0585d4ae5fe47924edae171b58213023004f1d 1545 1544 2020-04-10T11:03:24Z Chris 2 /* Neues & Änderungen */ mal schauen, ob das Einblenden aller Einträge funktioniert... wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <a href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">alles</a> </div> 2df2bbb7abfbac99637cb11db694dd150a2cb2db 1546 1545 2020-04-10T11:05:16Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">alles</a></html> </div> 066fe6c06adc9bcd2928fe25ca57a76b85600f8d 1547 1546 2020-04-10T11:08:13Z Chris 2 it verks :) wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> 6a309a0ae8987f89fcf832e49c04825d4c3e64be 1579 1547 2020-05-10T19:06:18Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder#VBus-Adapter_f.C3.BCr_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder#VBus-Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder#Hardware für den PC|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> 889e3be94b202fc02004ac5476129858b12ec99e Hobbyelektronik.org:Impressum 4 4 1548 1433 2020-04-17T20:02:16Z Chris 2 /* Spenden */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung nur eine Konversation in 2-3 Jahren mit verschlüsselten Mails stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Es geht um Dinge, die mich interessieren (oder einmal interessierten). Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schnell (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzprüfung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich "übrige" Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das "schlechte Gewissen" zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine "Win-Win-Win-Situation": Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, genauso die Kosten für den Versand.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. "Absolut richtig" zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krebshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und "Bettelbriefe" steckt. * Fragwürdig halte ich ebenfalls PeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kirche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Kirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) a97f13cda33573d74e17a5a36071bd8957a1d08e Briefkasteninnenbeleuchtung 0 445 1549 1156 2020-04-27T19:54:38Z Chris 2 /* Trivia */ Sie lebt noch :) wikitext text/x-wiki Zugegeben, es hört sich nicht nur bescheuert an, es ist auch so. Trotzdem hatte ich das Bedürfnis, eine Briefkasteninnenbeleuchtung zu bauen. Warum? Nein, nicht (nur) weil ich es kann, sondern weil sie durchaus praktisch ist = Problemstellung = Die Briefkästen des Mietshauses hier sind freistehend und in der dunklen Jahreszeit sieht man aufgrund der etwas ungünstig installierten Außenbeleuchtung durch den Einwurf nicht, ob Post gekommen ist. Durch das Öffnen der Frontklappe sieht und bekommt man zwar den Inhalt, aber dazu bin ich bei der geringen Anzahl von eintrudelnden Briefen schlicht zu faul. Umbauten müssen rückstandsfrei zu entfernen sein, schließlich will ichs nicht mit meinen Vermietern verscherzen. = Idee = In den Briefkasten soll mindestens eine LED, die durch das Öffnen des Deckels aktiviert wird. Die Befestigung findet über Magnete statt, die Stromversorgung durch Batterien. Damit diese nicht unnötig leergesaugt werden, soll die Beleuchtung zeitlich begrenzt sein. = Umsetzung = Zumindest bei der LED ist die Sache schnell klar: weiße PLCC2 liegen hier mehr als genug herum. Um sie sinnvoll zu betreiben, kommen 3 Mignon-Batterien in Serie zum Einsatz. Bei 3,3 Volt (also wenn die Zellen schon halb-platt sind) sind 7 mA mehr als genug, der passende Widerstand hierfür wäre 171 Ohm. Wäre, weil ein einfacher Vorwiderstand an dieser Stelle dumm ist - die Batteriespannung wird mit dem Ladestand fallen - und damit der Strom durch die LED. == LED-Treiber == Besser ist es deshalb, eine Konstantstromquelle zu verwenden. Die lässt sich sehr einfach aufbauen, zwei Transistoren und zwei Widerstände reichen. Der Strom wird über den unteren Widerstand und Transistor definiert: letzterer wird leitend, wenn seine Basis-Emitter-Spannung über ca. 0,7 Volt steigt - diese Spannung muss beim gewünschten Strom eingeprägt werden. Für den Widerstand gilt also: :<math>\textrm{R}=\frac{0.7}{\textrm{I}_\textrm{out}}</math> Der obere Transistor steuert den Strom durch die LED. Der Widerstand dient lediglich als Pull-up und ist daher eher unkritisch. Wer ihn hinreichend groß Dimensionierung will, muss sich den LED-Strom und den Verstärkungsfaktor ansehen. Die mechanische Integration ist einfach: ich habe noch kleine Leiterkärtchen, eigentlich für einen anderen Zweck, aber es passt alles für diese Schaltung drauf. Schrumpfschlauch drüber, kleine Magnete ran, nochmal Schrumpfschlauch. <gallery> Datei:Einfacher_LED-Treiber.png|Schaltplan des einfachen LED-Treibers Datei:Briefkasten_led.jpg|Aufgebauter LED-Triber mit LED, Magnet und Schrumpfschlauch </gallery> Bilder der Innereien gibt es leider keine. == Schalter == Für die Erkennung ob der Deckel offen ist gibt es viele Möglichkeiten: mechanischer Taster, Näherungssensoren, Neigungsschalter, Hallswitches, etc.. Mechanische Schalter brauchen in aller Regel viel Kraft (und viel Gegenkraft, die kann ich bei der Montage nicht bieten) und sind oft empfindlich gegen Feuchtigkeit. Viele Näherungssensoren (optisch, kapazitiv und induktiv) sind aktiv und haben einen relativ großen Eigenverbrauch. Nichts für langen Batteriebetrieb. Neigungsschalter geht, war aber früher dank Quecksilber eine ziemliche Sauerei; die aktuellen sind wahrscheinlich besser aber ich habe aufgrund des Temperaturbereichs Vorbehalte. Schlussendlich habe ich einen Reed-Kontakt verwendet. Hermetisch abgeschlossen, kraftfrei und kein Ruhestrom. Wenn man mechanisch faul ist oder nicht genug Grips in der Birne hat, braucht man einen Öffner - genau das (bzw. einen Wechsler) habe ich bestellt. Um die Integration vorweg zu nehmen: der Kontakt ist auf einer kleinen länglichen Leiterkarte gelandet - lang genug, um einen Magnet zur Montage am Briefkasten verwenden zu können. Jetzt kommt auch die Sache mit dem Grips: Der "Montagemagnet" war stark genug, damit das durch das Metall des Briefkastens verlaufende Feld den Kontakt öffnete. Mit geschickter Positionierung beider Magnete (der zur Montage und dem im Deckel) hätte ich die Felder so ausrichten können, dass sie sich im Deckel-zu-Fall neutralisiert hätten. Hätte-hätte... Aber auch so funktioniert es. Um vor Feuchtigkeit besser geschützt zu sein, kommt alles in Schrumpfschlauch und wird natürlich auf der etwas besser geschützten Seite des Briefkastens installiert. <gallery> Datei:Briefkasten_sensor.jpg|unten: Reedschalter auf Leiterkarte mit Magnet, oben (überbelichtet): Magnet </gallery> == Abschaltautomatik == {{Infobox AVR | Typ = ATtiny13 | Takt = 0,6 | FuseH = FF | FuseL = 61 }} Eigentlich wäre diese prädestiniert für eine Analogschaltung oder einen NE555. Schlussendlich wurde es aber ein ATtiny13. Der ist mit der Aufgabe zwar gänzlich unterfordert, braucht dafür im Schlaf nahezu keinen Strom und zudem fast keine Außenbeschaltung Das Programm könnte sehr einfach sein: Port initialisieren, Pin an, warten, Pin aus. Mit 4,8 MHz Takt braucht der Controller einige Milliampere, was in beiderlei Hinsicht unnötig viel ist. Über die CLKDIV-Fuse kann der Takt auf ein Achtel reduziert werden - besser aber trotzdem nicht überragend. Was ich beim Programmieren übersehen habe: den Watchdog als Taktquelle - 128 kHz und noch etwas stromsparender. Im [http://www.atmel.com/images/doc2535.pdf Datenblatt] kann man sich dazu Figure 19-1 und 19-5 anschauen. Demnach braucht der Chip bei 600 kHz (bei externer Taktquelle) zwischen 0,3 und 0,5 mA - mit dem Watchdog wären es lediglich 0,06 bis 0,09 mA. Statt warten per Delay kann man auch den internen Timer verwenden und die CPU bei Overflow wecken. Nur leider kann man mit weiterlaufendem Takt den Tiny nicht tief genug schlafen schicken, damit es richtig gut wird. Geht man in den Tiefschlaf, bleibt der Takt komplett weg und das war dann für den Timer. Glücklicherweise kann man den Watchdog so konfigurieren, dass er keinen Reset sondern einen Interrupt auslöst. Da er einen eigenen Oszillator hat, ist er zudem unabhängig vom Systemtakt. Sein Vorteiler lässt sich bis in den angenehmen Sekundenbereich einstellen. Im Power-Down und aktivem Watchdog braucht der Prozessor (Figure 19-14) zwischen 4,5 und 7,0 µA. Nachdem das Programm durch ist und sich der Bursche schlafen legt, sinkt der Stromverbrauch (Figure 19-13) auf sehr niedrige 0,2 bis 1,2 µA. Wo liegt nochmal die Selbstentladung von Alkali-Zellen? == Batteriewächter == Darf's ein bisschen mehr sein? Der ATtiny13 hat einen ADC, warum also nicht noch zusätzlich eine Warnung für bald leere Batterien einbauen? Einige AVRs können den ADC verkehrte Welt spielen lassen: Man kann die interne Referenz als Eingang wählen und die Versorgungsspannung als Referenz. Dadurch wird das Ergebnis zwar reziprok aber die Messung braucht keine externe Beschaltung und ist zudem sehr stromsparend. Geht hier leider nicht (Figure 14-1). Es muss also ein externer Spannungsteiler her. Der braucht permanent einen gewissen Strom und das ist Mist. Man kann die Widerstände zwar nach oben dimensionieren, dann wird die Messung durch ADC-bedingte Verfälschungen ungenauer. Ich bin einen etwas faulen (im Sinne von: warum mehr Zeit verschwenden) Kompromiss eingegangen: Der Spannungsteiler wird vom Schaltsignal für die LEDs versorgt. Dadurch haut der Strom nur für die maximal 30 Sekunden ab und zugleich hat der FET einen Pull-down am Gate, falls der IO doch mal floatet. Der Pad-Treiber im AVR dürfte einen leichten Spannungsabfall haben, aber zum einen kann man kalibrieren und zum anderen wird keine besonders hohe Genauigkeit benötigt. Bei der Dimensionierung muss man - wie bereits erwähnt - darauf achten, dass die Messung halbwegs sauber funktioniert aber gleichzeitig nicht unnötig viel Strom verbraucht wird. Natürlich muss auch der Teiler passen. Für diesen Zweck verwende ich gerne [https://www.muellerzumhagen.de/widerstand-ist-zwecklos-pointless-resistance/ Widerstand ist zwecklos], das die Paarung 33 kOhm (top) und 10 kOhm (bottom) ausspuckte. Damit ergibt sich eine maximal messbare Spannung von 4,73 V und ein Stromverbrauch von nicht ganz 105 µA bei 4,5 V. Die Auflösung wäre damit nicht ganz 4,6 mV - deutlich mehr als genug. Der ADC-Wert berechnet sich theoretisch wie folgt: :<math>\textrm{ADC}= \textrm{U}_{\textrm{bat}} \cdot \frac{10\textrm{ k}\Omega}{10\textrm{ k}\Omega+33\textrm{ k}\Omega} \cdot \frac{1024}{1.1\textrm{ V}}</math> Die Messung selbst ist geradeaus: Auswählen der Referenz und Eingang (PB4), Takt festlegen, Interrupt an und los geht's. Um etwas sinnvolles zu machen während die Messung durchgeführt wird, legt sich der Kern schlafen und wird wieder geweckt, sobald diese durch ist (sei(); nicht vergessen!). Anschließend wird der ADC-Wert ausgelesen und der Hardware-Block wieder deaktiviert. Um etwas bessere Ergebnisse zu erlangen, wird die Batteriespannung nicht direkt nach dem Start sondern nach einer Sekunde durchgeführt. Dadurch lassen sich zwei Dinge verknüpfen: Die Batterien sehen eine Last und man ist am richtigen Zeitpunkt, um die LEDs kurz auszuschalten - sollte die Batterieapannung das gesetzte Limit unterschritten haben. <gallery> Datei:Briefkasten_sch1.png|Schaltung </gallery> === Kalibrierung === Aufgrund der Beschaltung sah ich mich genötigt, den ADC zu testen. Der einfachste Weg dafür wäre UART, den es aber nicht gibt. Zumindest nicht in Hardware. Das Format ist relativ einfach, siehe [[wpde:Universal_Asynchronous_Receiver_Transmitter|Wikipedia]]. Idle high, Startbit, Daten und ein bisschen Pause fürs Stopbit (die ich mir gespart hab). Mit dem Wissen, wie lange ein NOP in der CPU dauert die Timings angepasst und los geht's. Mit "normalen" USB<>UART-Adaptern hat man allerdings wenig Spaß: meine Implementierung verwendet - der Faulheit wegen - 10 Datenbits und eine ziemlich krumme Baudrate, die halt einfach gerade gepasst hat. Der Logic Analyzer kann das, die meisten Wandler aber nicht. Aber wer will schon Interoperabilität? Das Ende vom Lied: die Berechnung von oben ist hinreichend genau. == Einbau == Dank der Magnete (Sensor + LEDs) und der Gravitation (Akkus und Mikrocontroller) lässt sich alles befestigen, wo es hin soll. Die Feinausrichtung des Reed-Kontakts geht schnell und einfach. = Es geht besser = Kein Projekt würde mal zweimal genau gleich machen. So auch hier. * LED-Treiber mit FET statt Bipolar-Transistoren aufbauen und dann auch gleich den gemeinsamen FET zum Schalten der Treiber sparen, indem die Versorgung von den Transistoren direkt vom Mikrocontroller kommt. * Spannungsteiler eine Nummer größer dimensionieren und etwas mehr Ungenauigkeit (who cares?!) in Kauf nehmen. Genauso würde ich im AVR gleich den Watchdog als Taktquelle nehmen. * Als Reed-Kontakt einen Schließer nehmen, ihn durch den Befestigungsmagnet "vorspannen" und das Feld durch den Magnet im Deckel neutralisieren. Geht sicher auch auf länger gut und senkt die Bauteilkosten. * Verringern der Betriebsdauer auf 10 Sekunden. Wer starrt schon 30 Sekunden in einen Briefkastenschlitz? <gallery> Datei:Briefkasten_sch2.png|Der etwas verbesserte Schaltplan </gallery> = Unterm Strich = Es ist wirklich sehr praktisch! Die Bilder unten wurden mit gleicher Belichtungseinstellung (mit eingeschalteter Außenbeleuchtung) aufgenommen und spiegeln in etwa die menschliche Helligkeitswahrnehmung wider: <gallery> Datei:Briefkasten_geschlossen.jpg|Geschlossen Datei:Briefkasten_offen.jpg|Geöffnet Datei:Briefkasten_oben.jpg|Blick von oben (keine Post) </gallery> = Trivia = * Der Freund meiner Nachbarin hält mich jetzt wohl für wahnsinnig, weil ich minutenlang vor dem Briefkasten stand und ihn öffnete und schloss ohne ihn zu bemerken. Warum schleicht er auch so herum? * Durch die Mechanische Verkopplung kann man das Klicken des Reedkontakts tatsächlich hören. * Auch nach gut 3 Jahren (12/2016 - 4/2020) funktioniert die Beleuchtung noch tadellos = Download = [[Datei:Briefkasten.zip|Schaltplan & Firmware]] [[Kategorie:AVR]] e3231d0981171155f965833eb760ed448266b3a9 USB-Fußtaster 0 623 1550 1539 2020-05-10T18:07:15Z Chris 2 wikitext text/x-wiki [[Datei:Footswitch.jpg|thumb|Fertig aufgebauter Fußtaster]] "Schau Mama, freihändig!" Wer kennt das nicht? Man muss auf mehreren Leiterkarten verschiedene Spannungen messen. Üblicherweise läuft es dann wie folgt ab: # Messspitzen platzieren # Wert vom Messgerät ablesen # Messspitzen ablegen und zum PC umdrehen # Messwert eintippen # Zurückdrehen, Messspitzen wieder in die Hände nehmen # Nochmal nachschauen, welcher Messpunkt jetzt dran ist # Wiederholen Ab und zu mischt sich dann das erneute Messen ein, weil ein Wert unplausibel ist und man entweder einen Zahlendreher drin oder schneller getippt als gedacht hat. Unterm Strich ist es auf jeden Fall sehr zeitraubend und nervig. Gleichzeitig baumeln die Füße unbeteiligt am Stuhl herunter. Die meisten Messgeräte (und anderes Laborequipment) lassen sich über den PC kontrollieren, warum also nicht gleich die richtigen Werte z. B. nach Excel transferieren? Nur irgendwie muss man den Prozess anstoßen... =Die schnelle Lösung= Tastatur ist blöd, also muss eine andere Eingabemöglichkeit her. Ein Taster und eine Projektbox ist schnell gefunden, Loch in die Box und ein paar große Schrauben dazu (damit sie nicht gleich abhaut) und fertig ist der improvisierte Fußtaster. Nur wie kommt die Info in den PC? Die serielle Schnittstelle hat neben Rx und Tx oft auch Steuerleitungen – aus den alten Tagen, in denen Modems noch so richtig langsam waren. Diese lassen sich in so ziemlich jeder Programmiersprache kontrollieren und abfragen. Ein FT232 liegt auch noch herum, also Taster angelötet und los geht’s! Das Programm ist in Python geschrieben, pollt die CTS-Leitung und sobald diese low wird, wird per pyVisa den Multimeter der aktuelle Messwert entlockt, passend formatiert und mit dem Keyboard-Modul "ausgetippt". Damit die Augen am Mikroskop bleiben können, wird zudem ein kurzer Piepton ausgegeben. Sehr viel Spaß für wenig Geld. Leider muss man bei jeder Benutzung schauen, welcher COM-Port dem Adapter zugeordnet wurde und ob dieser auch wirklich im Script steht. =Die schöne Lösung= Eines Tages brachte mein Kollege einen kleinen Pappkarton vom [https://www.pollin.de Ramschmax] mit, Inhalt: [https://www.pollin.de/p/fusstaster-pfs-135a-10-a-250-v-420705 420705]. Ein Gusseiserner Fußtaster mit schönem Klick-Klack-Mikroschalter. Der hat etwas Besseres als den schnöden UART-Adapter mit Zwillingslitze verdient – endlich wieder eine schöne Anwendung für [https://www.obdev.at/vusb/ V-USB]! Was soll das Teil können? Am besten natürlich so viel wie möglich, damit es vielleicht sogar als "Adaptive Controller" dienen kann. Deshalb habe ich mich dafür entschieden, einen Multidevice-Ansatz zu fahren. Das umfasst aktuell: * Generisches USB-HID * Einzeltasten-Tastatur * Makro-Tastatur * Joystick =Hardware= Die Hardware könnte nicht einfacher sein - sie entspricht größtenteils dem [https://www.obdev.at/products/vusb/easylogger.html Easylogger]-Beispielprojekt, nur dass anstelle der automatischen Oszillator-Kalibrierung ein externer Quarz verwendet wird. Hintergrund hierfür ist, dass das [[SNES-Joypad]], das sich selbst kalibriert (oder zumindest sollte), am RetroPie beim Booten oft nicht erkannt wird. Kann aber auch gut sein, dass es sich um einen Bug in meiner Firmware handelt. Die Bauteile sind - abgesehen vom Quarz und Mikrocontroller in SMD-Bauform. Als MCU werkelt fürs Erste ein ATtiny85, der später noch herunterskaliert werden kann. Die Wahl auf das DIP-Gehäuse fiel, um ohne Löten die Firmware herunterzuladen. Mit Quarz als Taktquelle bleibt noch ein "richtiger" IO übrig (sofern man den Reset-Pin nicht deaktiviert) - mehr braucht man nicht. Eine eigens designte Leiterkarte ist aufgrund der Einfachheit der Schaltung völlig unnötig, aber es war noch Platz auf dem Panel... <gallery> footswitch 1.0 sch.png|Schaltplan footswitch 1.0 top.png|Bestückungsplan Oberseite footswitch 1.0 bot.png|Bestückungsplan Unterseite footswitch 1.0 assy.jpg|Aufgebaute Leiterkarte </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || MA03-1 || |- | 1 || SV1 || || MA04-1 || GC 2212-EU030 |- | 1 || C1 || 100n || C0603 || X7R-G0603 100N |- | 1 || C4 || 10u || C0805 || KEM X7R0805 10U |- | 1 || Q1 || 12M || HC49U-V || 12,0000-HC49U-S |- | 1 || R11 || 150 || R0603 || RND 0603 1 150 |- | 1 || C5 || 150n || C0603 || X7R 0603FCE 150N |- | 2 || C2, C3 || 22p || C0603 || RND 150MT18N2202 |- | 1 || R3 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || R10 || 4k7 || R0603 || RND 0603 1 4,7k |- | 2 || R1, R2 || 68 || R0603 || RND 0603 1 68 |- | 1 || IC1 || ATTINY 85-20 PU || DIL08 || ATTINY 85-20 PU |- | 2 || D1, D2 || BZX84C3V6 || SOT23 || SMD ZD 3,6 |} Leider stellte sich erst zu spät heraus, dass die Leiterkarte ein bisschen zu groß ist, um sie an der eigentlich vorgesehenen Stelle zu montieren. Man kann sie zwar ein bisschen schräg anschrauben und von der Ecke noch etwas Material wegnehmen, aber dann ist die USB-Leitung auch wieder im Weg. Das Design ist also nicht so richtig geglückt... Aber kein Problem, dass man nicht mit ein bisschen Schrumpfschlauch lösen könnte: <gallery> footswitch 1.0 designflaw 1.jpg|Dort sollte die Leiterkarte hin footswitch 1.0 designflaw 2.jpg|...und hier ist sie footswitch 1.0 designflaw 3.jpg|weitere Perspektive </gallery> Der Schirm ist übrigens auf ein Stück Leitung gecrimpt, das wiederum an die Halterung des Tasters gelötet ist. =Firmware= ==Firmware== {{Infobox AVR | Typ = ATtiny85 | Takt = 12 | FuseH = D7 | FuseL = DE | FuseE = FF }} Die Firmware ist mehr oder weniger viergeteilt, entsprechend den verschiedenen Modi. Hierfür gibt es mehrere Gründe: * die freien VID/PID-Paare sind auf die verschiedenen Funktionen beschränkt und es lässt sich nicht zweifelsfrei sagen, ob Multi-Endpoint-Konfigurationen erlaubt sind * Die Fragmentierung macht den Code (teilweise) einfacher und übersichtlicher * Keinerlei Treiberprobleme (es gibt wohl Betriebssysteme, die sich an Multi-Endpoint verschlucken) * Es ist nicht ganz so üblich und in der Implementierung interessanter Nach dem Reset liest die Firmware den zu verwendenden Modus aus dem EEPROM. Ist diese ungültig oder der IO des Tasters auf Masse gezogen, wird der auf Generisches HID gesetzt. Gegenüber des USB-Treibers wird nun auch der Pointer für die USB-Deskriptoren gesetzt (die sich wiederum im Flash befinden). Anschließend läuft die Initialisierung der unterschiedlichen Modi und es wird in die entsprechende Endlosschleife gesprungen. Als USB VID/PID-Paare werden von obdev frei zur Verfügung gestellten verwendet: * HID: 0x16C0/0x27D9 * Tastatur: 0x16C0/0x27DB * Gamepad: 0x16C0/0x27DC Im Grunde ist das alles kein Hexenwerk, allerdings haben die "Dynamisierung" der USB-Deskriptoren einiges an (auf dem Attiny schwierige) Fehlersuche gekostet. Über Manche Dinge, wie z. B. wie man die verschiedenen Deskriptoren den Anfragen zuordnet, ist die Dokumentation leider etwas vage (oder ich habe sie nicht richtig gelesen/falsch gesucht). Auch lässt sich die Firmware noch ziemlich optimieren, das gesteckte Ziel wäre, dass sie auf den ATtiny45 passt. Aktuell ist hauptsächlich die RAM-Belegung ein Problem (und noch nicht optimal). =Konfiguration= Um die Konfiguration des Fußtasters ändern zu können, muss er sich in Modus 2 (Generisches HID) befinden. Sollte dieser Modus nicht aktiv sein, kann er erreicht werden indem der Taster gedrückt wird, während der USB-Stecker verbunden wird. In den Report-Beispielen werden stets hexadezimale Zahlen verwendet. Angaben mit <code>xx</code> sind beliebig bzw. müssen ignoriert werden. ==Keycodes== Bevor auf die verschiedenen Funktionen im Detail eingegangen wird, ein paar Worte zu den Keycodes: Tastaturen sind seit jeher ziemlich einfach gestrickt. So "weiß" der Controller der Tastatur zwar an welcher Position eine Taste gedrückt wird, aber nicht welches Layout sie vertritt - dies wird erst durch das Betriebssystem umgesetzt. Das hat zum Beispiel den Effekt, dass mit einer deutschen Tastatur an einem auf Englisch eingestellten PC u. a. Y und Z vertauscht sind (und man beim Raspberrz Pi das Passwort mindestens einmal falsch eingibt). Diese Eigenschaft betrifft natürlich auch den Fußtaster. Die Keycodes für englische Tastaturen können in der Spezifikation [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 "Universal Serial Bus HID Usage Tables"] in der aktuellen Version ab Seite 53 (Kapitel 10 Keyboard/Keypad Page (0x07)]) nachgeschlagen werden. Für das deutsche Layout befindet sich eine Tabelle im Download-Bereich (keine Garantie auf Vollständigkeit und Korrektheit). ==Modus 0: Generisches HID== Die Kommunikation findet über Report ID 0 mit 8 Datenbytes statt. Beim Senden von Reports definiert das erste Byte den Befehl, in den weiteren befinden sich die Parameter dessen: {| class="wikitable" ! Nummer || Befehl || Beschreibung |- | 0 || NOP || Keine Operation, dieser Code wird bei den Antworten für den Status des Tasters verwendet |- | 1 || Restart || Neustart des Mikrocontrollers (ersetzt das Aus- und Einstecken nachdem der Modus umgestellt wurde) |- | 2 || Lesen Modus || Gibt den Interface-Modus zurück |- | 3 || Setzen Modus || Setzt den Interface-Modus |- | 4 || Lesen Einzeltaste || Gibt den Keycode der Einzeltasten-Tastatur zurück |- | 5 || Setzen Einzeltaste || Setzt den Keycode der Einzeltasten-Tastatur |- | 6 || Lesen Tastensequenz || Gibt 6 Byte der Sequenz des angegebenen Blocks (in Byte 1) zurück |- | 7 || Setzen Tastensequenz || Setzt die 6 Bytes der Sequenz des angegebenen Blocks (in Byte 1) |} Jeder Befehl wird beantwortet, wobei dem ersten Byte eine Statusinformation mit bitweise Oder hinzugefügt wird: {| class="wikitable" ! Nummer || Status || Beschreibung |- | 0x00 || None || Wird nicht verwendet |- | 0x40 || Busy || Der Befehl wurde nicht ausgeführt, weil der Controller beschäftigt ist |- | 0x80 || Ok || Der Befehl wurde erfolgreich ausgeführt, die optionale Antwort befindet sich in den restlichen Bytes |- | 0xC0 || Error || Beim Ausführen des Befehls ist ein Fehler aufgetreten |} ===Tastenstatus=== Für jede Änderung des Tastenstatus wird ein Report übertragen: <code>&lt; <span class="hb1">00</span> <span class="hb2">BB</span> xx xx xx xx xx xx</code> * <span class="hb1">"Befehl": Status der Taste</span> * <span class="hb2">Status der Taste - 0: nicht gedrückt, 1: gedrückt</span> ==Modus 1: Einzeltasten-Tastatur== In diesem Modus verhält sich der Fußtaster wie die Taste einer Tastatur. Die zu drückende Taste kann über Modus 2 festgelegt werden. Leider ist es aktuell noch nicht möglich, Multimedia-Tasten (Wiedergabesteuerung, Lautstärke, Anwendungssteuerung) zu verwenden. ===Lesen=== Zum Zurücklesen der verwendeten Taste muss folgender Report gesendet werden: <code>&gt; <span class="hb1">04</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste</span> Die Antwort entspricht folgendem Muster: <code>&lt; <span class="hb1">84</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste (OK)</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) ** 0x01: Steuerung links ** 0x02: Umschalttaste links ** 0x04: Alt links ** 0x08: GUI links (u. a. Windows-Taste) ** 0x10: Steuerung rechts ** 0x20: Umschalttaste rechts ** 0x40: Alt rechts (müsste Alt+Gr sein) ** 0x80: GUI rechts (müsste Kontextmenü sein) * <span class="hb3">Keycode Taste</span> ===Schreiben=== Zum Setzen einer Taste folgender Report gesendet werden: <code>&gt; <span class="hb1">05</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Setzen Einzeltaste</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) * <span class="hb3">Keycode Taste</span> Die restlichen Bytes im Report werden ignoriert. Die Bestätigung wird wie unter "Modus 2" beschrieben gesendet. Da keine Readback stattfindet, wird immer mit "OK" geantwortet: <code>&lt; <span class="hb1">85</span> xx xx xx xx xx xx xx</code> ==Modus 2: Makro-Tastatur== Über die Makro-Tastatur können längere Tastenfolgen ausgegeben werden. Für diesen Zweck sind 128 Byte im EEPROM vorgesehen, was einer maximalen Folge von etwa 63 Anschlägen entspricht. Aktuell kann nur eine Taste gleichzeitig gedrückt werden kann - ein Rollover ist dementsprechend nicht möglich. Die Ausgabe erfolgt mit maximaler Geschwindigkeit, also mit etwa 100 Anschlägen pro Sekunde, wobei zwischen gleichlautenden Anschlägen sowie nach dem letzten Zeichen automatisch ein Loslassen der Taste eingefügt wird, was zu einer kleinen Verzögerung führt und damit das Timing verändert Beispiel: Bei der Ausgabe des Wortes <code>Hallo</code> folgende Reports übertragen: * Umschalttaste drücken, Taste "H" drücken * Umschalttaste loslassen, Taste "A" drücken * Taste "L" drücken * Taste "L" loslassen * Taste "L" drücken * Taste "O" drücken * Taste "O" loslassen So dauert die Übertragung des Wortes - bei einem Report-Intervall von 10 ms - etwa 70 ms statt den zunächst anzunehmenden 50 ms. ===Datenformat=== Die Daten werden im Muster <code>Befehl + Daten</code> gespeichert, wobei die Datenlänge dynamisch (aber anhand des Befehls ersichtlich) ist. Dementsprechend sind die Befehle teilweise als Flags aufgebaut, zum besseren Verständnis hier im Binärformat: * <code>0b<b>11111111</b></code>: Ende der Sequenz (entspricht nicht beschriebenen Speicherzellen), keine Daten * <code>0b<b>1</b><span class="hb1">ppppppp</span></code>: Pause in 5 ms-Schritten, p = 0 ... 126, t = (p + 1) * 5 ms, maximal 635 ms, keine Daten * <code>0b<b>0</b><span class="hb2">mm</span><span class="hb3">xx</span>xxx</code>: Verhalten der Modifier ** <code><span class="hb2">0b00</span></code>: Modifier beibehalten, keine Daten ** <code><span class="hb2">0b01</span></code>: Modifier für nachfolgende Taste drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb2">0b10</span></code>: Modifier dauerhaft halten, +1 Byte Daten ** <code><span class="hb2">0b11</span></code>: Modifier loslassen, keine Daten * <code>0b<b>0</b><span class="hb2">xx</span><span class="hb3">kk</span>xxx</code>: Verhalten der Taste ** <code><span class="hb3">0b00</span></code>: Taste beibehalten, keine Daten ** <code><span class="hb3">0b01</span></code>: Taste einmal drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb3">0b10</span></code>: Taste dauerhaft halten (bis eine andere Taste gedrückt wird), +1 Byte Daten ** <code><span class="hb3">0b11</span></code>: Taste loslassen, keine Daten Sollen Modifier und Taste mit einem Befehl verändert werden, wird zuerst der Modifier erwartet, dann die Taste: <code>0b0<span class="hb2">10</span><span class="hb3">01</span>000 <span class="hb4">0b00000010</span> <span class="hb5">0b00001011</span></code> <span class="hb2">Drückt und hält</span> die <span class="hb4">linke Umschalttaste</span> und drückt die <span class="hb5">Taste H (0x0B)</span> <span class="hb3">einmal</span>. Beispiel: Es soll die Zeichenfolge <code>Hallo WELT</code> mit anschließendem Zeilenumbruch ausgegeben werden, mit einer Pause von 500 ms nach "Hallo". Die Sequenz sieht nun wie folgt aus (Binär und Hex gemischt, Hex für Keycodes): {| class="wikitable" ! Code || Befehl || Parameter |- | <code>0b0<span class="hb1">01</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x0B</span></code> || <span class="hb1">Modifier einmal drücken</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Linke Umschalttaste</span>, <span class="hb4">Taste H</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x04</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste A</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x12</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste O</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1100011</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Pause mit 99 Zeiteinheiten</span>: t = (99 + 1) * 5 ms = 500 ms |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb3">0x2C</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Leertaste</span> |- | <code>0b0<span class="hb1">11</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x1A</span></code> || <span class="hb1">Modifier drücken und halten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Rechte Umschalttaste</span>, <span class="hb4">Taste W</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x08</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste E</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x17</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste T</span> |- | <code>0b0<span class="hb1">10</span><span class="hb2">00</span>000</code> || <span class="hb1">Modifier loslassen</span>, <span class="hb2">Kein Tastendruck</span> || - |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x28</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Return-Taste</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1111111</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Ende der der Sequenz</span> |} ===Lesen=== Wie bereits in der Befehlsübersicht erwähnt, erfolgt das Lesen und Schreiben der Sequenzdaten in Blöcken: <code>&gt; <span class="hb1">06</span> <span class="hb2">CC</span> xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> Als Antwort bekommt man dann die Daten des jeweiligen Blocks: <code>&lt; <span class="hb1">86</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Lesen Sequenz (OK)</span> * <span class="hb2">Blocknummer: 0 ... 21 </span> * <span class="hb2">6 Datenbytes des Blocks</span> Ist der letzte Block nicht "füllend", sind die restlichen Bytes zufällig, ebenso kann über das "End of Sequence" hinaus gelesen werden. ===Schreiben=== Das Schreiben von Blöcken ist der Antwort vom Lesen sehr ähnlich: <code>&gt; <span class="hb1">07</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Schreiben Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> * <span class="hb2">6 Datenbytes des Blocks</span> Sobald die Daten geschrieben wurden, antwortet der Mikrocontroller mit: <code>&lt; <span class="hb1">06</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Schreiben Sequenz (OK)</span> ==Modus 3: Gamepad== Es ist keine Konfiguration notwendig, das Gamepad meldet sich mit einer Taste und kann in Anwendungen wie gewohnt zugeordnet werden. <gallery> footswitch_gamepad.png|Eigenschaftenseite in Windows </gallery> Leider erkennt weder Firefox 73 noch Chromium 82 das Pad im html5gamepad-Tester. Anzumerken ist, dass wie bei der Einzeltasten-Tastatur Reports nur bei Zustandsänderung der Taste gesendet werden. Bis jetzt konnte ich dadurch keine Einschränkungen feststellen. =PC-Software= Aktuell gibt es eine kleine Python-Lib und ein paar Beispiele dazu. Siehe Downloads. =Anmerkungen= * Die Firmware auf dem Tiny85 zu entwickeln war grauenvoll, da man nur sehr schlecht debuggen kann. Das nächste Mal lieber auf einem Mikrocontroller mit deutlich mehr IOs und Hardware-UART entwickeln und anschließend auf ein kleineres Geschwister portieren * [https://github.com/micronucleus/micronucleus/ micronucleus] ist ein USB-Bootloader basierend auf V-USB, den ich bis jetzt noch nicht verwendet habe, in Zukunft aber sollte * Der Quellcode steht, wie von objective development gefordert, unter GPLv2 =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= * [[Datei:Footswitch.zip]] Schaltplan & Layout in EAGLE 7.7.0, Firmware & Sourcen in Atmel Studio 7, Beispielanwendung in Python 3.7 =Weblinks= * [https://www.uwe-sieber.de/usbtreeview.html USB Device Tree Viewer] zeigt sehr detaillierte Infos zu angeschlossenen USB-Geräten an * [http://wireshark.org/ Wireshark] kann auch USB tracen * [https://eleccelerator.com/usbdescreqparser/ USB Descriptor and Request Parser] * [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 Universal Serial Bus HID Usage Tables, Seite 53: 10 Keyboard/Keypad Page (0x07)] [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] [[Kategorie:Kleine Helferlein]] 0b89b432b67aa859146ad8efed7a1e9d26a31d2d Datei:Anykeyx6 plm.png 6 676 1551 2020-05-10T18:10:54Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 shim.png 6 677 1552 2020-05-10T18:10:54Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 sketchup taste seite.png 6 678 1553 2020-05-10T18:10:55Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 pwm.png 6 679 1554 2020-05-10T18:10:55Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 beleuchtung konzentrisch.jpg 6 680 1555 2020-05-10T18:10:55Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 sketchup taster unten.png 6 681 1556 2020-05-10T18:10:55Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 sketchup bodenplatte.png 6 682 1557 2020-05-10T18:10:56Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 sketchup deckel.png 6 683 1558 2020-05-10T18:10:56Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 druckmuster deckel.jpg 6 684 1559 2020-05-10T18:10:59Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 Deckel.jpg 6 685 1560 2020-05-10T18:10:59Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 komplett.jpg 6 686 1561 2020-05-10T18:10:59Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 boden und deckel.jpg 6 687 1562 2020-05-10T18:10:59Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 beleuchtung diffusor.jpg 6 688 1563 2020-05-10T18:11:00Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 deckel assy.jpg 6 689 1564 2020-05-10T18:11:00Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 taste einzelteile.jpg 6 690 1565 2020-05-10T18:11:01Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 sch.png 6 691 1566 2020-05-10T18:11:02Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 1583 1566 2020-05-10T20:12:33Z Chris 2 Chris lud eine neue Version von [[Datei:Anykeyx6 sch.png]] hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 tastenverdrahtung.jpg 6 692 1567 2020-05-10T18:11:02Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 bodenplatte benippelt.jpg 6 693 1568 2020-05-10T18:11:02Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 deckel verklebt.jpg 6 694 1569 2020-05-10T18:11:02Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 taste LED.jpg 6 695 1570 2020-05-10T18:11:03Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 taste iterationen.jpg 6 696 1571 2020-05-10T18:11:03Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 deckel vergurkt.jpg 6 697 1572 2020-05-10T18:11:03Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 rgb demo.jpg 6 698 1573 2020-05-10T18:11:05Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 platine.jpg 6 699 1574 2020-05-10T18:11:06Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Anykeyx6 demo.mp4 6 700 1575 2020-05-10T18:12:04Z Chris 2 Hochgeladen mit [[mw:Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Anykey x6 0 701 1576 2020-05-10T18:12:38Z Chris 2 Seite erstellt wikitext text/x-wiki [[Datei:anykeyx6_komplett.jpg|thumb|Fertig aufgebaute Hardware (Farben leicht retuschiert)]] Meine Schwester ist Lehrerin. Ein Job, um den ich sie nicht beneide - gerade in 2020. Hier in Bayern fängt (Stand Anfang Mai) das Leben an der Schule langsam wieder an, parallel zum Unterricht in den Schulen müssen jedoch die daheim bleibenden Kinder noch unterrichtet werden. Wenn man die eigene Arbeit ernst nimmt, ist das kein Spaß. Klar, man könnte für das Eigenstudium einfach Arbeitsblätter über den Zaun werfen und auf Seiten in den Büchern verweisen, aber wenn ich da an meine eigene Schulzeit und die eher extrinsische Motivation denke... Obwohl meine Schwester schon sehr viel digital hat, braucht Unterricht (gerade bei Sprachen) auch jemanden, der/die vor der Klasse spricht und natürlich ist eigenständiges Lernen für viele nicht ganz einfach. Aus diesem Grund hat meine Schwester angefangen, Videos zu machen. Vorerst nur mit ausgedruckten Blättern und dem Handy auf dem Stativ. Um Ihre digitalen Materialien besser nutzen zu können, fragte sie dann doch mal nach einem screen recorder. [https://obsproject.com/ OBS] war schnell installiert und eingerichtet. Blöd nur, dass sie keinen zweiten Monitor (bzw. Displayport-Adapter) für ihr MS Surface hat. Damit ihre Schüler sie auch mal sehen können (oder auch mal "Tafelunterricht" zu machen), habe ich ihr mehrere Szenen in OBS eingerichtet: * Bildschirmaufnahme * Bildschirmaufnahme + Kamera in der Ecke * Kamera Blöd ist nur, dass sie ohne besagten zweiten Bildschirm für jede Aktion OBS in den Vordergrund holen muss. Zwar kann man dort auch globale Hotkeys anlegen, aber ohne vollständige Tastatur läuft man sehr schnell Gefahr, Doppelbelegungen zu bekommen und dadurch sehr merkwürdiges Verhalten am PC zu haben. Gleichzeitig sieht man nicht, was OBS nun tatsächlich macht. Ja, man kann eine Fernbedienung für OBS auf dem Tablet oder Smartphone installieren, aber das schafft eigentlich nur mehr Probleme als es löst, zumal man die (freien) Clients, die ich auf Anhieb gefunden hab für jede Session neu konfigurieren muss. Zudem muss das Gerät am Laufen halten und kann die Tasten nicht erfühlen. Das lenkt unnötig ab und erhöht auch die Akzeptanz nicht wirklich. Auch fertige Lösungen wie das Elgato Stream Deck ist für die (hoffentlich) kurze Nutzungsdauer unverhältnismäßig teuer. Gleichzeitig sitzt hier ein Ingenieur herum, der aufgrund der aktuellen Situation erst einmal Gleitzeit abbaut. =Die Idee= Da kann man doch was basteln. Ein paar Taster, ein paar LEDs, ein bisschen Firmware und noch ein paar Zeilen Code auf dem PC. Was soll daran so aufwändig sein? Um eines vorweg zu nehmen: Übers Ziel hinausschießen, das kann daran aufwändig werden. Ziel ist, 6-8 bunt beleuchtete Taster zu haben, die in OBS eingebunden werden können. Der Mikrocontroller ist schnell gefunden. Um nicht zu weit von den Codebeispielen von [https://www.obdev.at/products/vusb/index-de.html V-USB] zu sein, soll ein oller ATmega8 zum Einsatz kommen. Weil ich schon länger was mit intelligenten LEDs machen wollte, liegt schon viel zu lange ein Streifen mit WS2812B herum. Der Plan war, diese – womöglich sogar noch auf dem Streifen – auf Taster zu kleben. Natürlich muss der [[wpde:Woman acceptance factor|WAF]] auch halbwegs passen, deshalb ist ein nicht zu schäbiges Gehäuse angesagt. 3D-Ducker sei dank bin ich auch dazu (zumindest seitens der Ausstattung) in der Lage. =Elektronik= Die Ernüchterung kam schneller als erwartet. Dass die Ansteuerung der LEDs zeitkritisch ist, wusste ich. Dass das auch für V-USB gilt, ebenfalls. Dass man beides nicht so einfach kombinieren kann, würde dann sehr schnell klar. Der USB-Stack braucht zwingend einen Pin-Interrupt, für die Ansteuerung der LEDs muss dieser aber abgeschaltet werden – sonst blinkt alles wie ein Weihnachtsbaum auf LSD. Tim (aka cpldcpu) hat sich die Mühe gemacht, V-USB mit [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling zu ermöglichen] - gleichzeitig sogar mit entsprechender LED. Den Weg wollte ich nicht gehen, weil das potenziell an anderen Stellen schmerzhaft werden könnte. Ok, was nun? Ein Coprozessor, der UART/I²C auf das LED-Protokoll umwandelt? Eigentlich wollte ich kein Mehrprozessor-System bauen – und auch hier bleibt das Problem mit Interrupts vs. keine Interrupts, auch durch die Einschränkungen durch USI dürfte das noch etwas unentspannter sein. Da ist guter Rat teuer. Auf einfarbige LEDs wollte ich aber auch nicht zurückgehen. ==LED-Treiber== 6 RGB-LEDs mit PWM anzusteuern, braucht es 18 PWM-Kanäle. Das hat glaube ich kein AVR8. ich habe zwar noch einen PCA9685 herumliegen, der aber auch nur 16 Kanäle bereitstellt. Zudem nimmt das Teil mit seinem Breakout-Board relativ viel Platz ein. Zu viel für das, was ich vor dem inneren Auge habe. Habe ich 18 Kanäle geschrieben? Jein. Betreibt man Multiplexing, reichen zwischen 3 und 6. Schlussendlich habe ich mich dafür entschieden, die Farben in den Multiplex zu nehmen und den PWM pro Taste laufen zu lassen - mit entsprechenden Einbußen der Helligkeit (ein Drittel). Aber wo bekommt man an einem ATmega8 6 synchrone PWM-Kanäle her? Ganz einfach: gar nicht. Zumindest in Hardware - anders schaut es in Software aus, wo es auch keine richtige PWM ist, sondern eher eine Pulsleistungsmodulation (kurz PDM - einen passenden Begriff konnte ich finden, daher die Neukreation), wie sie 2011 auf der [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite] schon beschrieben wurde. Um es kurz zu beschreiben: bei gewöhnlicher PWM gibt es für jeden Kanal zwei Schaltzeitpunkte, von denen einer pro Kanal individuell ist (da er den Helligkeitswert vorgibt). Hat man n Kanäle, gibt es n Zeitpunkte, die man möglichst zielgenau treffen muss. Gerade wenn diese nah beieinander liegen, kann das zu Timingproblemen führen. Der hier verwendete Dimmer funktioniert anders. Man muss dabei bedenken, dass es beim Dimmen von LEDs relativ egal ist, ob sie über einen Zyklus am Stück an sind, oder ob sie zwischendurch ausgeschaltet werden können - wichtig ist unterm Strich nur, wie viel sie im im Laufe eines Zyklus aktiv sind. Bei einer Auflösung von b bit gibt es bei dieser Methode b Zeitpunkte - ganz egal wie viele Kanäle man verwendet und: deren Timing ist fest. Zudem sind diese sind zeitlich immer mit Faktor 2 voneinander getrennt. Nun schaltet man den Kanal immer dann an, wenn im Helligkeitswert das "Bit" des zugehörigen Zeitschlitzes aktiv ist. Da es visuell deutlich besser als mit Text funktioniert, hier mal zwei Beispiele mit einer Modulation mit 3 Bit. Die Wertigkeit steht links, die An-Zeiten entsprechen den grünen Blöcken (deren X-Achse der Zeit entspricht) und die nötigen Interrupts sind mit roten Pfeilen markiert: <gallery> anykeyx6_pwm.png | Pulsweitenmodulation anykeyx6_plm.png | Pulsleistungsmodulation </gallery> Betrachtet man die aktive Fläche der einzelnen Helligkeitswerte, kommt man auf das gleiche - nur dass die PDM deutlich ressourcenschonender ist. Dazu kommt der Effekt, dass durch das "Zerhacken" der PWM die LEDs mit einer höheren Frequenz flackern (auch wenn sie variiert). Dadurch wird der Stroboskop-Effekt verringert - des einen Freud ist des anderen Leid: achtet man auf EMV, wird es and er Stelle unangenehmer. Aber genug dazu. Aufgrund des Multiplexing gibt es, wie oben beschrieben, nur ein Drittel an Helligkeit. Die meisten LEDs halten bei pulsförmiger Ansteuerung deutlich mehr Strom als im Dauerbetrieb aus weil der limitierende Faktor die Erwärmung ist. Da die LEDs (im 5050-Gehäuse) für den Aufbau von einem LED-Streifen "geerntet" wurden, habe ich kein Datenblatt zur Komponente, aber Wissen: z. B. kommt für den roten Strang ein 330 Ohm-Widerstand zum Einsatz, bei 12 V und 3 roten LEDs in Reihe mit ca. 1,85 V Vorwärtsspannung sind das etwa 20 mA. Ohne weitere Infos zu maximalen Strömen und weil die Helligkeit eigentlich reichen sollte, bin ich bei diesem Strom geblieben. ==Taster== Die Taster kommen direkt an IOs und sind gegen Masse verschaltet. Eine rudimentäre Entprellung wird in Software gemacht. ==USB== Die USB-Beschaltung entspricht weitestgehend der aus den Beispielen von Objective Development. Aus reiner Faulheit habe ich die Schutzbeschaltung vom [[USB-Fußtaster]] übernommen. Sprichwörtlich: Die nötigen Bauteile bestückt und die Leiterkarte auf die passende Größe gestutzt. ==Schaltplan== Die gesamte Schaltung ist also relativ einfach. Als FETs für die LEDs kommen BSS84 (p-Kanal, aufseiten der Anoden) und BSS138 (n-Kanal, aufseiten der Kathoden) zum Einsatz. Aufgrund der Komplexität reicht es als Handskizze: <gallery> anykeyx6_sch.png | Schaltplan - unbekannter Künstler, 2020, digital </gallery> =Firmware= Die Firmware ist erstaunlich einfach, zumal ich mich nicht sonderlich bemüht habe. Die LEDs werden mit der oben beschriebenen Methode (in leddrv.c) angesteuert, wobei zusätzlich noch eine Fading-Funktion zum Einsatz kommt. Das entlastet den USB-Stack und verringert das Flackern (siehe weiter unten) Die Tasten werden (sofern die PWM nicht höhere Priorität hat) jede Millisekunde abgefragt (<code>buttons_tick()</code>) und wenn der Pegel low (Taste gedrückt) ist, ein Zähler inkrementiert. Bei High-Pegel wird der Zähler auf 0 zurückgesetzt. Ist der Zähler größer als 10, gilt die entsprechende Taste gedrückt. Alle Buttons in einem Byte können über die Methode <code>buttons_values()</code> abgefragt werden. In Sachen USB wird ein Out-Report (PC -> Device) mit Netto 16 Byte und ein In-Report mit Netto 8 Byte (Device -> PC) verwendet. Der Out-Report dient zum Setzen der LEDs und sieht wie folgt aus: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index der LED (1-6) * <span class="hb2">Rx</span>: Rot-Wert der LED (0 ... 255) * <span class="hb3">Gx</span>: Grün-Wert der LED (0 ... 255) * <span class="hb4">Bx</span>: Blau-Wert der LED (0 ... 255) * <span class="hb5">Tx</span>: Dauer für den Übergang (0 ... 255, in 5 ms-Schritten) Es können somit 3 Farben gleichzeitig geschrieben werden, Index 0 wird nicht verwendet, da es üblicherweise der Init-Wert für Arrays ist und somit nicht versehentlich die Farbe einer Taste gesetzt wird. Der In-Report ist denkbar einfach, im ersten Byte steht das Bit-Muster der aktuell gedrückten Taster: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> Der Report wird bei jeder Änderung des Zustands der Taster gesendet. Das ist in mehrerlei Hinsicht nicht ganz ideal, da zum einen der Initiale Zustand (nach Öffnen des Devices) nicht ermittelt werden kann und falls doch mal ein USB-Paket verloren geht, verpasst man Tastendrücke. Aber: es musste schnell gehen. =Mechanik= Die Mechanik ist (zumindest für mich als Neuling in Sachen Design und 3D-Druck) ein Stück aufwändiger. Einfach nur die Leiterkarte auf den Tisch zu knallen geht hier nicht, es muss nicht wie aus dem Ei gepellt aussehen, aber nicht nur aus der Kategorie "form follows function" sein. Um schnell voran zu kommen, kam das MS Paint im 3D-Design zum Einsatz: SketchUp. Mit allen Einschränkungen und fehlender Parametrisierung bin ich darin leider noch immer am schnellsten, etwas für den Druck vorzubereiten. ==Tasten== Mit ein bisschen Zeichnen in 2D-Software stellte sich heraus, dass rechteckige Tasten mit 15 mm Breite und Höhe, einer Abrundung mit Radius 2,5 mm und einem Abstand von 5 mm zueinander eine angenehme Haptik aufweisen. Ein erstes Muster mit Kragen (damit die Taste nicht durchs Gehäuse fällt) ist schnell gedruckt - mit transparentem PLA, (wenn ich mich richtig erinnere) 50 % Infill und konzentrischem Top/Bottom-Pattern (in Cura gesliced) ist schnell gedruckt und sieht, nachdem er mit Farbe beschmiert wurde um zu sehen wie dicht der Druck ist auch nach dem Reinigen versaut aus. Licht geht durch, sieht aber eher bescheiden aus: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Ausleuchtung bei konzentrischem Druck </gallery> Als nächstes kommt die Frage: wie die LEDs und Taster montieren? um das mechanische Design zu vereinfachen, habe ich die Idee verfolgt, möglichst Gleichteile zu verwenden. In meinen letzten Leiterkarten-Bestellungen habe ich im Waste immer 1x1 mm Kupferflächen im 1,27 mm-Raster platziert, ein Streifen damit ist etwa 9,6 mm breit (bei 1,6 mm Materialdicke) - eine gute Größe für diese Anwendung. LED auf die eine Seite, Taster auf die andere und eine Idee, für die mich die Mechaniker in der Arbeit (völlig zu Recht) vermutlich nicht mehr anschauen würden: Constraining auf zwei Bezugsebenen. Normalerweise strebt man an, dass sich die Toleranzen von einer Seite aus ausbreiten, damit man die Toleranzketten in Griff halten kann. Würde hier heißen: Die Tasten sind auf die Gehäusefront referenziert und dementsprechend müssen die Taster auch an einer Ebene montiert werden, deren Toleranz sich auf die Front bezieht. Bei mir sollen die Taster aber gegen die Bodenplatte drücken. Mit vielen Nachteilen. Da es sich aktuell allerdings um ein Einzelstück handelt: Egal. Das Platinchen mit LED vorne und Taster hinten wird einfach in eine Nut im Taster eingeschoben. Bis auf einen kleinen (reproduzierbaren) Druckfehler funktioniert das prächtig. Hier die verschiedenen Designiterationen: <gallery> anykeyx6_taste_iterationen.jpg | Iterationen der Tasten 1 bis 5.5 anykeyx6_sketchup_taste_seite.png | Finales Modell der Tasten von der Seite anykeyx6_sketchup_taster_unten.png | und von unten anykeyx6_taste_einzelteile.jpg | Einzelteile der Tasten (der Taster fehlt) anykeyx6_taste_LED.jpg | Leiterkarte in die Taste eingeschoben </gallery> Mit Infill auf 100 % und der Tasterfront auf dem Druckbett entsteht eine relativ schöne Oberfläche. Da Concentric Top/Bottom-Pattern ein Kreuz in der Diagonale erzeugt hat, bin ich auf "Lines" umgestiegen, das die Taster, gemeinsam mit dem konzentrischen Rahmen fast schon "wie gekauft" aussehen lässt. Um eine bessere Farbmischung zu erzeugen (und die Taster eine eigenwillige Streuwirkung haben), habe ich etwas Band aus meinem Beschriftungsgerät (Wenn es wichtig ist: Brother P-touch) hinter den Taster geklebt. Dadurch wird die Ausleuchtung der drei LED-Kristalle zumindest ein bisschen homogener: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Zum Vergleich nochmal das Bild von oben (konzentrischer Druck) anykeyx6_beleuchtung_diffusor.jpg | links ohne Folie, rechts mit </gallery> Insgesamt hat das Sandwich eine Höhe von 12,4 mm - 0,25 mm weniger, wenn der Taster gedrückt ist. Der Kragen ist 2,5 mm nach innen versetzt. Das, plus die Dicke der Gehäuseteile, wird die Gesamtdicke des Geräts. =Gehäuse= Mit den Maßen der Tasten geht es los, wobei die Ausschnitte für diese um 0,25 mm in alle Richtungen erweitert wurden. Das bringt zwar etwas Spiel, aber bevor der Cutter angesetzt oder nochmals gedruckt werden muss, dürfen die Tasten eher ein bisschen wackeln - zumal es bei den ersten Tastern ordentlich Elefantenfüße gab. Mit einem Überstand von 7,5 mm von der Kante der Taster zu den Gehäusewänden in drei Richtungen und etwas mehr (17,5 mm) in die vierte Richtung - irgendwo muss ja die Elektronik hin - ist das Gehäuse relativ kompakt. Im inneren befinden sich zwischen den Tastern 4 mm hohe Wände - nicht zum Ausrichten, sondern vielmehr um Streulicht zwischen den Tastern zu vermeiden. Damit sich das Gehäuse nicht durchbiegt und dadurch versehentlich mehrere Taster auf einmal betätigt werden, befinden sich in den Kreuzungspunkten der Taster Erhöhungen, die die Stabilität in Z-Richtung erhöhen. Um Material und vor allem Druckzeit zu sparen, gab es zwei abgeschnittene Druckmuster, die man dank transparentem Filament auf weißem Grund fast nicht sieht: <gallery> anykeyx6_druckmuster_deckel.jpg | Druckmuster für die Aufnahme der Tasten </gallery> Als Zugentlastung des fest installierten USB-Kabels befindet sich hinter dem U-förmigen Ausschnitt eine kleine Rampe und ein Loch, durch den ein Kabelbinder passt. Die Rampe dient lediglich dazu, dass der Kabelbinder die untere Gehäusehälfte nicht nach unten drückt. Man könnte mutmaßen, dass durch die Druckschichten bedingte Treppenstruktur die Leitung sogar ein bisschen verhakt wird. 3 Löcher, durch die M2,5-Schrauben passen, dienen zur Befestigung der Bodenplatte. Insgesamt gab es 4 Iterationen, wobei nur zwei den Weg auf den Drucker gefunden haben - und das auch nur, weil sich das erste Druckteil vom Druckbett abgelöst und dadurch unschön verzogen hat. Anscheinend sind die STL-Daten nicht ganz sauber, wodurch das Modell wohl etwas in der Luft hängt. Durch einen Microstep von -0,001 in Z-Richtung wurde das Druckergebnis besser, aber die erste Lage ist trotzdem noch etwas lückig... <gallery> anykeyx6_sketchup_deckel.png | 3D-Modell des Deckels anykeyx6_deckel_vergurkt.jpg | Der erste Versuch (vergurkt) anykeyx6_Deckel.jpg der | Der bessere Druck. </gallery> Das untere Gehäuseteil sind eigentlich 7 Teile und brauchte keine Revision (aber einen kleinen Eingriff mit dem Skalpell). Die Komplexität ist auch deutlich geringer. Auffallend sind zunächst die 4 "Kamine" - die Idee dahinter ist, Muttern einzulegen und diese mit dem oberen Gehäuseteil zu verschrauben. Das ganze ist (eher unbeabsichtigt) auf Pressung designed, sowohl für die Mutter, als auch in Richtung anderes Gehäuseteil. Immerhin rutscht nichts. An den Positionen der Taster befinden sich Sacklöcher/Kerben - aus einem sehr einfachen Grund: Material und Druckzeit sparen. Die Bodenplatte soll in weiten Teilen dick genug sein, dass sie stabil ist aber auf keinen Fall ein zweites Mal gedruckt werden muss. Um die Taster in der Höhe einzupassen, werden kleine Distanznippel eingesetzt, die klein sind und dadurch sehr schnell angepasst und gedruckt werden können. Weil ich keinen Sekundenkleber mehr da hatte, sind sie lediglich einseitig auf der Bodenplatte mit doppelseitigem Klebeband befestigt. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D-Modell der Bodenplatte anykeyx6_shim.png | Das 3D-Modell eines Nippel anykeyx6_bodenplatte_benippelt.jpg | Bodenplatte mit Muttern und Nippeln </gallery> Insgesamt war der Drucker etwa 4 Stunden beschäftigt, wobei er auch nicht mit maximaler Geschwindigkeit lief. Die Materialkosten liegen (ohne Probestücke und Fehldrucke) bei etwa 50 cent wenn ich mich nicht täusche, also nicht wirklich der Rede wert. =Zusammenbau= Ursprünglich habe ich einen Atmega8 im DIP-Gehäuse vorgesehen. Da es aber doch ein bisschen eng geworden wäre, kam dann doch einer im TQFP-Gehäuse zum Einsatz. Neben dem Mikrocontroller finden auch die 9 Transistoren für die LED-Ansteuerung Platz auf der Selfmade-Punktrasterplatine: <gallery> anykeyx6_platine.jpg | Bestückte Leiterkarte. </gallery> Die LED-Tasten bekommen gehörig lange Anschlussleitungen aus Kupferlackdraht, die durchgepiepst und auf passend beschriftete Klebebandstreifen landen. Miteinander verdrillt und verlötet kommen sie dann an die FETs. Gleiches Spiel für die Massen der Taster. <gallery> anykeyx6_tastenverdrahtung.jpg | Etwas Ordnung im Chaos <gallery> Damit die Tasten beim Zusammenfügen nicht immer wieder aus ihren Löchern entwischen, kommt Klebeband von außen auf das Gehäuse. Zur Sicherheit mit Nummern beschriftet, damit mit Drehen und Spiegeln nix schief geht. Tasten eingelegt, Leitungen im Gehäuse verlegt und den Kupfer-Knäuel zusammengedrückt. Papa sagte schon immer: Salat ist gesund. Das USB-Kabel liegt fest verzurrt und sehr engem Biegeradius im Gehäuse - hält (hoffentlich). <gallery> anykeyx6_boden_und_deckel.jpg | Beide Gehäusehälften anykeyx6_deckel_verklebt.jpg | Bestückungshilfe anykeyx6_deckel_assy.jpg | Deckel mit eingelegten Komponenten </gallery> In die untere Gehäusehälfte sind die Nippel schon eingeklebt und es wird spannend: passt es? Leider sind keine Senkkopfschrauben im Haus, also bleibt es mit den verzinkten Zylinderkopf-Schrauben etwas hässlich. Oder pragmatisch. Naja, es hält - und die Tasten liegen so im Gehäuse, dass sie weder (allzu sehr) klappern noch permanent gedrückt werden. Erfolg! :) Um bei den Tasten nicht im kompletten Blindflug zu sein, ziert noch ein Label und ein paar Symbole der FontAwesome die obere Reihe. Damit sollte nun nichts mehr schief geben. =Software= ==Erster Test== Die erste Testsoftware ist in Python geschrieben und lässt einen Regenbogen durchlaufen. Der Einfachheit halber fasst sie nur eine LED gleichzeitig an: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> Sieht dann als Momentaufnahme in etwa wie folgt aus: <gallery> anykeyx6_rgb_demo.jpg | Farben, yay! </gallery> ==Der OBS-Client== Ein "echtes" Plugin für OSB Studio zu schreiben spare ich mir mangels Tiefe in C++. Stattdessen nutze ich [https://github.com/Palakis/obs-websocket obs-websocket], das eine API für C# anbietet, die extrem einfach zu bedienen ist. Für die Buttons ist eine extrem rudimentäre Klasse sehr schnell zusammengehackt. Gänzlich ohne Fehlerbehandlung. Das Auslesen der Buttons erfolgt in einem Background-Worker, der Events feuert (und beim Loslassen zusätzlich die Dauer des Drückens ermittelt), das Setzen der LED-Farben erfolgt für alle 6. Hier merkt man auch wie heiß die Nadel ist mit der gestrickt wird: Zwischen dem Schreiben der beiden "Sets" legt sich die Software für eine Millisekunde schlafen. Der Grund einst einfach die dämlich - schreibt man zu schnell, geht evtl. das erste der beiden Datenpakete in der Firmware verloren, weil die Übergabe nicht (wenn man es so nennen will) threadsafe ist. Die GUI hat lediglich einen "Connect"-Button, der nur gedrückt werden sollte, wenn OBS läuft und die Hardware verbunden ist. Die Konfiguration ist ebenfalls eher grundlegend und in AnykeyOBS.exe.config zu finden. Hier kann für jede Taste die Aktiv/Inaktiv-Farbe als Hex-Code (oder named color, ungetestet) abgelegt werden, die Funktion definiert und ein Argument für diese Funktion angegeben werden. Zum Zuordnen einer Szene packt man in die Funktion "Scene" und schreibt den zugehörigen Szenen-Namen ins Argument. Für die Aufnahme heißt die Funktion "Record" und als Argument kann "Toggle", "Start" und "Stop" definiert werden. Streaming wird noch nicht unterstützt. Aus mir nicht ganz verständlichen Gründen kann der Zustand des Streamings/Recordings nur über Events ermittelt werden, dadurch bleibt die Taste mit entsprechender Zuordnung beim Start des Programms orange. Dies ist auch die (fest hinterlegte) Farbe für Übergänge zwischen Aufnahme und keine Aufnahme. Ein weiteres Feature ist das Abbrechen einer Funktion - Grundsätzlich werden die Aktionen erst beim Loslassen des Tasters getriggert - außer man drückt diesen länger als eine Sekunde. In diesem Fall wird die Aktion abgebrochen. Insgesamt kann man die Software allerhöchstens als Proof of Concept bezeichnen. Es funktioniert, irgendwie. ===Feuerprobe=== Mittlerweile durfte ich meine Schwester sogar besuchen, um ihr die Hardware zu geben. yay! Das Einrichten fand aber trotzdem online statt. obs-websockt installiert, AnykeyOBS aufs Tablet und: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Mist. Die vermutliche Ursache ist schnell gefunden: Bei manchen USB-Geräten kann der Name nicht gelesen werden. Eine Packung try-catch auf das Problem geworfen und eine Prise <code>Console.WriteLine</code>s und das Programm bleib nach dem Klick auf "Connect" geöffnet. "Leuchten die Knöppe?" - "Oh mann, wie geil" - "Also ja?". Danach hörte ich nur noch wildes Klicken. Ich glaube, das Teil gefällt. Und so sieht es aus: [[Datei:anykeyx6_demo.mp4]] =Fazit= Wo fange ich an? Beim Guten, beim Schlechten oder bei den Sachen, für die ich mich schäme? Unterm Strich: für eine sehr hemdsärmelig zusammengestrickte Hardware sieht es (ohne dass ich mich selbst loben möchte) ganz ordentlich aus. Schlimm wird es erst, wenn man unter die Haube schaut. Das dafür aber auch konsequent. Das Gute: * Meine Schwester hat etwas, das ihr hoffentlich die Arbeit etwas erleichtert * Ich habe wieder einiges in Sachen 3D-Druck gelernt * Es hat ziemlich viel Spaß gemacht * Alles ist bunt Das Schlechte: * Decoupling, welches Decoupling? * LEDs ** Nicht sonderlich hell ** Flackern bei USB-Traffic (durch INT0) ** In dunkler Umgebung zu hell und bei Tageslicht schlecht sichtbar * Das Setzen von LEDs und Tastendrücke können verschluckt werden * Taster ** Können auch von der Gehäuseunterseite betätigt werden ** Relativ laut (im Video hörbar) ** Wackeln, sind schief und haben keine Führung * Software ** An allen Ecken und Enden rudimentär, wenn etwas ausfällt, funktioniert erst einmal nichts ** Kein automatisches Verbinden mit OBS und der Hardware ** Keine GUI für die Konfiguration ** So gut wie keine Funktionen in OBS unterstützt ** Außer OBS-Steuerung keine weiteren Funktionen * Keine Standby-States =Downloads= * SketchUp-Dateien, zugehörige STLs, Firmware und C#-Software um mit OBS zu sprechen. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] a8128d1a88ff04b379ca30e20392a54d41ff3270 1577 1576 2020-05-10T18:15:22Z Chris 2 Close-Tag in gallery vergessen wikitext text/x-wiki [[Datei:anykeyx6_komplett.jpg|thumb|Fertig aufgebaute Hardware (Farben leicht retuschiert)]] Meine Schwester ist Lehrerin. Ein Job, um den ich sie nicht beneide - gerade in 2020. Hier in Bayern fängt (Stand Anfang Mai) das Leben an der Schule langsam wieder an, parallel zum Unterricht in den Schulen müssen jedoch die daheim bleibenden Kinder noch unterrichtet werden. Wenn man die eigene Arbeit ernst nimmt, ist das kein Spaß. Klar, man könnte für das Eigenstudium einfach Arbeitsblätter über den Zaun werfen und auf Seiten in den Büchern verweisen, aber wenn ich da an meine eigene Schulzeit und die eher extrinsische Motivation denke... Obwohl meine Schwester schon sehr viel digital hat, braucht Unterricht (gerade bei Sprachen) auch jemanden, der/die vor der Klasse spricht und natürlich ist eigenständiges Lernen für viele nicht ganz einfach. Aus diesem Grund hat meine Schwester angefangen, Videos zu machen. Vorerst nur mit ausgedruckten Blättern und dem Handy auf dem Stativ. Um Ihre digitalen Materialien besser nutzen zu können, fragte sie dann doch mal nach einem screen recorder. [https://obsproject.com/ OBS] war schnell installiert und eingerichtet. Blöd nur, dass sie keinen zweiten Monitor (bzw. Displayport-Adapter) für ihr MS Surface hat. Damit ihre Schüler sie auch mal sehen können (oder auch mal "Tafelunterricht" zu machen), habe ich ihr mehrere Szenen in OBS eingerichtet: * Bildschirmaufnahme * Bildschirmaufnahme + Kamera in der Ecke * Kamera Blöd ist nur, dass sie ohne besagten zweiten Bildschirm für jede Aktion OBS in den Vordergrund holen muss. Zwar kann man dort auch globale Hotkeys anlegen, aber ohne vollständige Tastatur läuft man sehr schnell Gefahr, Doppelbelegungen zu bekommen und dadurch sehr merkwürdiges Verhalten am PC zu haben. Gleichzeitig sieht man nicht, was OBS nun tatsächlich macht. Ja, man kann eine Fernbedienung für OBS auf dem Tablet oder Smartphone installieren, aber das schafft eigentlich nur mehr Probleme als es löst, zumal man die (freien) Clients, die ich auf Anhieb gefunden hab für jede Session neu konfigurieren muss. Zudem muss das Gerät am Laufen halten und kann die Tasten nicht erfühlen. Das lenkt unnötig ab und erhöht auch die Akzeptanz nicht wirklich. Auch fertige Lösungen wie das Elgato Stream Deck ist für die (hoffentlich) kurze Nutzungsdauer unverhältnismäßig teuer. Gleichzeitig sitzt hier ein Ingenieur herum, der aufgrund der aktuellen Situation erst einmal Gleitzeit abbaut. =Die Idee= Da kann man doch was basteln. Ein paar Taster, ein paar LEDs, ein bisschen Firmware und noch ein paar Zeilen Code auf dem PC. Was soll daran so aufwändig sein? Um eines vorweg zu nehmen: Übers Ziel hinausschießen, das kann daran aufwändig werden. Ziel ist, 6-8 bunt beleuchtete Taster zu haben, die in OBS eingebunden werden können. Der Mikrocontroller ist schnell gefunden. Um nicht zu weit von den Codebeispielen von [https://www.obdev.at/products/vusb/index-de.html V-USB] zu sein, soll ein oller ATmega8 zum Einsatz kommen. Weil ich schon länger was mit intelligenten LEDs machen wollte, liegt schon viel zu lange ein Streifen mit WS2812B herum. Der Plan war, diese – womöglich sogar noch auf dem Streifen – auf Taster zu kleben. Natürlich muss der [[wpde:Woman acceptance factor|WAF]] auch halbwegs passen, deshalb ist ein nicht zu schäbiges Gehäuse angesagt. 3D-Ducker sei dank bin ich auch dazu (zumindest seitens der Ausstattung) in der Lage. =Elektronik= Die Ernüchterung kam schneller als erwartet. Dass die Ansteuerung der LEDs zeitkritisch ist, wusste ich. Dass das auch für V-USB gilt, ebenfalls. Dass man beides nicht so einfach kombinieren kann, würde dann sehr schnell klar. Der USB-Stack braucht zwingend einen Pin-Interrupt, für die Ansteuerung der LEDs muss dieser aber abgeschaltet werden – sonst blinkt alles wie ein Weihnachtsbaum auf LSD. Tim (aka cpldcpu) hat sich die Mühe gemacht, V-USB mit [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling zu ermöglichen] - gleichzeitig sogar mit entsprechender LED. Den Weg wollte ich nicht gehen, weil das potenziell an anderen Stellen schmerzhaft werden könnte. Ok, was nun? Ein Coprozessor, der UART/I²C auf das LED-Protokoll umwandelt? Eigentlich wollte ich kein Mehrprozessor-System bauen – und auch hier bleibt das Problem mit Interrupts vs. keine Interrupts, auch durch die Einschränkungen durch USI dürfte das noch etwas unentspannter sein. Da ist guter Rat teuer. Auf einfarbige LEDs wollte ich aber auch nicht zurückgehen. ==LED-Treiber== 6 RGB-LEDs mit PWM anzusteuern, braucht es 18 PWM-Kanäle. Das hat glaube ich kein AVR8. ich habe zwar noch einen PCA9685 herumliegen, der aber auch nur 16 Kanäle bereitstellt. Zudem nimmt das Teil mit seinem Breakout-Board relativ viel Platz ein. Zu viel für das, was ich vor dem inneren Auge habe. Habe ich 18 Kanäle geschrieben? Jein. Betreibt man Multiplexing, reichen zwischen 3 und 6. Schlussendlich habe ich mich dafür entschieden, die Farben in den Multiplex zu nehmen und den PWM pro Taste laufen zu lassen - mit entsprechenden Einbußen der Helligkeit (ein Drittel). Aber wo bekommt man an einem ATmega8 6 synchrone PWM-Kanäle her? Ganz einfach: gar nicht. Zumindest in Hardware - anders schaut es in Software aus, wo es auch keine richtige PWM ist, sondern eher eine Pulsleistungsmodulation (kurz PDM - einen passenden Begriff konnte ich finden, daher die Neukreation), wie sie 2011 auf der [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite] schon beschrieben wurde. Um es kurz zu beschreiben: bei gewöhnlicher PWM gibt es für jeden Kanal zwei Schaltzeitpunkte, von denen einer pro Kanal individuell ist (da er den Helligkeitswert vorgibt). Hat man n Kanäle, gibt es n Zeitpunkte, die man möglichst zielgenau treffen muss. Gerade wenn diese nah beieinander liegen, kann das zu Timingproblemen führen. Der hier verwendete Dimmer funktioniert anders. Man muss dabei bedenken, dass es beim Dimmen von LEDs relativ egal ist, ob sie über einen Zyklus am Stück an sind, oder ob sie zwischendurch ausgeschaltet werden können - wichtig ist unterm Strich nur, wie viel sie im im Laufe eines Zyklus aktiv sind. Bei einer Auflösung von b bit gibt es bei dieser Methode b Zeitpunkte - ganz egal wie viele Kanäle man verwendet und: deren Timing ist fest. Zudem sind diese sind zeitlich immer mit Faktor 2 voneinander getrennt. Nun schaltet man den Kanal immer dann an, wenn im Helligkeitswert das "Bit" des zugehörigen Zeitschlitzes aktiv ist. Da es visuell deutlich besser als mit Text funktioniert, hier mal zwei Beispiele mit einer Modulation mit 3 Bit. Die Wertigkeit steht links, die An-Zeiten entsprechen den grünen Blöcken (deren X-Achse der Zeit entspricht) und die nötigen Interrupts sind mit roten Pfeilen markiert: <gallery> anykeyx6_pwm.png | Pulsweitenmodulation anykeyx6_plm.png | Pulsleistungsmodulation </gallery> Betrachtet man die aktive Fläche der einzelnen Helligkeitswerte, kommt man auf das gleiche - nur dass die PDM deutlich ressourcenschonender ist. Dazu kommt der Effekt, dass durch das "Zerhacken" der PWM die LEDs mit einer höheren Frequenz flackern (auch wenn sie variiert). Dadurch wird der Stroboskop-Effekt verringert - des einen Freud ist des anderen Leid: achtet man auf EMV, wird es and er Stelle unangenehmer. Aber genug dazu. Aufgrund des Multiplexing gibt es, wie oben beschrieben, nur ein Drittel an Helligkeit. Die meisten LEDs halten bei pulsförmiger Ansteuerung deutlich mehr Strom als im Dauerbetrieb aus weil der limitierende Faktor die Erwärmung ist. Da die LEDs (im 5050-Gehäuse) für den Aufbau von einem LED-Streifen "geerntet" wurden, habe ich kein Datenblatt zur Komponente, aber Wissen: z. B. kommt für den roten Strang ein 330 Ohm-Widerstand zum Einsatz, bei 12 V und 3 roten LEDs in Reihe mit ca. 1,85 V Vorwärtsspannung sind das etwa 20 mA. Ohne weitere Infos zu maximalen Strömen und weil die Helligkeit eigentlich reichen sollte, bin ich bei diesem Strom geblieben. ==Taster== Die Taster kommen direkt an IOs und sind gegen Masse verschaltet. Eine rudimentäre Entprellung wird in Software gemacht. ==USB== Die USB-Beschaltung entspricht weitestgehend der aus den Beispielen von Objective Development. Aus reiner Faulheit habe ich die Schutzbeschaltung vom [[USB-Fußtaster]] übernommen. Sprichwörtlich: Die nötigen Bauteile bestückt und die Leiterkarte auf die passende Größe gestutzt. ==Schaltplan== Die gesamte Schaltung ist also relativ einfach. Als FETs für die LEDs kommen BSS84 (p-Kanal, aufseiten der Anoden) und BSS138 (n-Kanal, aufseiten der Kathoden) zum Einsatz. Aufgrund der Komplexität reicht es als Handskizze: <gallery> anykeyx6_sch.png | Schaltplan - unbekannter Künstler, 2020, digital </gallery> =Firmware= Die Firmware ist erstaunlich einfach, zumal ich mich nicht sonderlich bemüht habe. Die LEDs werden mit der oben beschriebenen Methode (in leddrv.c) angesteuert, wobei zusätzlich noch eine Fading-Funktion zum Einsatz kommt. Das entlastet den USB-Stack und verringert das Flackern (siehe weiter unten) Die Tasten werden (sofern die PWM nicht höhere Priorität hat) jede Millisekunde abgefragt (<code>buttons_tick()</code>) und wenn der Pegel low (Taste gedrückt) ist, ein Zähler inkrementiert. Bei High-Pegel wird der Zähler auf 0 zurückgesetzt. Ist der Zähler größer als 10, gilt die entsprechende Taste gedrückt. Alle Buttons in einem Byte können über die Methode <code>buttons_values()</code> abgefragt werden. In Sachen USB wird ein Out-Report (PC -> Device) mit Netto 16 Byte und ein In-Report mit Netto 8 Byte (Device -> PC) verwendet. Der Out-Report dient zum Setzen der LEDs und sieht wie folgt aus: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index der LED (1-6) * <span class="hb2">Rx</span>: Rot-Wert der LED (0 ... 255) * <span class="hb3">Gx</span>: Grün-Wert der LED (0 ... 255) * <span class="hb4">Bx</span>: Blau-Wert der LED (0 ... 255) * <span class="hb5">Tx</span>: Dauer für den Übergang (0 ... 255, in 5 ms-Schritten) Es können somit 3 Farben gleichzeitig geschrieben werden, Index 0 wird nicht verwendet, da es üblicherweise der Init-Wert für Arrays ist und somit nicht versehentlich die Farbe einer Taste gesetzt wird. Der In-Report ist denkbar einfach, im ersten Byte steht das Bit-Muster der aktuell gedrückten Taster: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> Der Report wird bei jeder Änderung des Zustands der Taster gesendet. Das ist in mehrerlei Hinsicht nicht ganz ideal, da zum einen der Initiale Zustand (nach Öffnen des Devices) nicht ermittelt werden kann und falls doch mal ein USB-Paket verloren geht, verpasst man Tastendrücke. Aber: es musste schnell gehen. =Mechanik= Die Mechanik ist (zumindest für mich als Neuling in Sachen Design und 3D-Druck) ein Stück aufwändiger. Einfach nur die Leiterkarte auf den Tisch zu knallen geht hier nicht, es muss nicht wie aus dem Ei gepellt aussehen, aber nicht nur aus der Kategorie "form follows function" sein. Um schnell voran zu kommen, kam das MS Paint im 3D-Design zum Einsatz: SketchUp. Mit allen Einschränkungen und fehlender Parametrisierung bin ich darin leider noch immer am schnellsten, etwas für den Druck vorzubereiten. ==Tasten== Mit ein bisschen Zeichnen in 2D-Software stellte sich heraus, dass rechteckige Tasten mit 15 mm Breite und Höhe, einer Abrundung mit Radius 2,5 mm und einem Abstand von 5 mm zueinander eine angenehme Haptik aufweisen. Ein erstes Muster mit Kragen (damit die Taste nicht durchs Gehäuse fällt) ist schnell gedruckt - mit transparentem PLA, (wenn ich mich richtig erinnere) 50 % Infill und konzentrischem Top/Bottom-Pattern (in Cura gesliced) ist schnell gedruckt und sieht, nachdem er mit Farbe beschmiert wurde um zu sehen wie dicht der Druck ist auch nach dem Reinigen versaut aus. Licht geht durch, sieht aber eher bescheiden aus: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Ausleuchtung bei konzentrischem Druck </gallery> Als nächstes kommt die Frage: wie die LEDs und Taster montieren? um das mechanische Design zu vereinfachen, habe ich die Idee verfolgt, möglichst Gleichteile zu verwenden. In meinen letzten Leiterkarten-Bestellungen habe ich im Waste immer 1x1 mm Kupferflächen im 1,27 mm-Raster platziert, ein Streifen damit ist etwa 9,6 mm breit (bei 1,6 mm Materialdicke) - eine gute Größe für diese Anwendung. LED auf die eine Seite, Taster auf die andere und eine Idee, für die mich die Mechaniker in der Arbeit (völlig zu Recht) vermutlich nicht mehr anschauen würden: Constraining auf zwei Bezugsebenen. Normalerweise strebt man an, dass sich die Toleranzen von einer Seite aus ausbreiten, damit man die Toleranzketten in Griff halten kann. Würde hier heißen: Die Tasten sind auf die Gehäusefront referenziert und dementsprechend müssen die Taster auch an einer Ebene montiert werden, deren Toleranz sich auf die Front bezieht. Bei mir sollen die Taster aber gegen die Bodenplatte drücken. Mit vielen Nachteilen. Da es sich aktuell allerdings um ein Einzelstück handelt: Egal. Das Platinchen mit LED vorne und Taster hinten wird einfach in eine Nut im Taster eingeschoben. Bis auf einen kleinen (reproduzierbaren) Druckfehler funktioniert das prächtig. Hier die verschiedenen Designiterationen: <gallery> anykeyx6_taste_iterationen.jpg | Iterationen der Tasten 1 bis 5.5 anykeyx6_sketchup_taste_seite.png | Finales Modell der Tasten von der Seite anykeyx6_sketchup_taster_unten.png | und von unten anykeyx6_taste_einzelteile.jpg | Einzelteile der Tasten (der Taster fehlt) anykeyx6_taste_LED.jpg | Leiterkarte in die Taste eingeschoben </gallery> Mit Infill auf 100 % und der Tasterfront auf dem Druckbett entsteht eine relativ schöne Oberfläche. Da Concentric Top/Bottom-Pattern ein Kreuz in der Diagonale erzeugt hat, bin ich auf "Lines" umgestiegen, das die Taster, gemeinsam mit dem konzentrischen Rahmen fast schon "wie gekauft" aussehen lässt. Um eine bessere Farbmischung zu erzeugen (und die Taster eine eigenwillige Streuwirkung haben), habe ich etwas Band aus meinem Beschriftungsgerät (Wenn es wichtig ist: Brother P-touch) hinter den Taster geklebt. Dadurch wird die Ausleuchtung der drei LED-Kristalle zumindest ein bisschen homogener: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Zum Vergleich nochmal das Bild von oben (konzentrischer Druck) anykeyx6_beleuchtung_diffusor.jpg | links ohne Folie, rechts mit </gallery> Insgesamt hat das Sandwich eine Höhe von 12,4 mm - 0,25 mm weniger, wenn der Taster gedrückt ist. Der Kragen ist 2,5 mm nach innen versetzt. Das, plus die Dicke der Gehäuseteile, wird die Gesamtdicke des Geräts. =Gehäuse= Mit den Maßen der Tasten geht es los, wobei die Ausschnitte für diese um 0,25 mm in alle Richtungen erweitert wurden. Das bringt zwar etwas Spiel, aber bevor der Cutter angesetzt oder nochmals gedruckt werden muss, dürfen die Tasten eher ein bisschen wackeln - zumal es bei den ersten Tastern ordentlich Elefantenfüße gab. Mit einem Überstand von 7,5 mm von der Kante der Taster zu den Gehäusewänden in drei Richtungen und etwas mehr (17,5 mm) in die vierte Richtung - irgendwo muss ja die Elektronik hin - ist das Gehäuse relativ kompakt. Im inneren befinden sich zwischen den Tastern 4 mm hohe Wände - nicht zum Ausrichten, sondern vielmehr um Streulicht zwischen den Tastern zu vermeiden. Damit sich das Gehäuse nicht durchbiegt und dadurch versehentlich mehrere Taster auf einmal betätigt werden, befinden sich in den Kreuzungspunkten der Taster Erhöhungen, die die Stabilität in Z-Richtung erhöhen. Um Material und vor allem Druckzeit zu sparen, gab es zwei abgeschnittene Druckmuster, die man dank transparentem Filament auf weißem Grund fast nicht sieht: <gallery> anykeyx6_druckmuster_deckel.jpg | Druckmuster für die Aufnahme der Tasten </gallery> Als Zugentlastung des fest installierten USB-Kabels befindet sich hinter dem U-förmigen Ausschnitt eine kleine Rampe und ein Loch, durch den ein Kabelbinder passt. Die Rampe dient lediglich dazu, dass der Kabelbinder die untere Gehäusehälfte nicht nach unten drückt. Man könnte mutmaßen, dass durch die Druckschichten bedingte Treppenstruktur die Leitung sogar ein bisschen verhakt wird. 3 Löcher, durch die M2,5-Schrauben passen, dienen zur Befestigung der Bodenplatte. Insgesamt gab es 4 Iterationen, wobei nur zwei den Weg auf den Drucker gefunden haben - und das auch nur, weil sich das erste Druckteil vom Druckbett abgelöst und dadurch unschön verzogen hat. Anscheinend sind die STL-Daten nicht ganz sauber, wodurch das Modell wohl etwas in der Luft hängt. Durch einen Microstep von -0,001 in Z-Richtung wurde das Druckergebnis besser, aber die erste Lage ist trotzdem noch etwas lückig... <gallery> anykeyx6_sketchup_deckel.png | 3D-Modell des Deckels anykeyx6_deckel_vergurkt.jpg | Der erste Versuch (vergurkt) anykeyx6_Deckel.jpg der | Der bessere Druck. </gallery> Das untere Gehäuseteil sind eigentlich 7 Teile und brauchte keine Revision (aber einen kleinen Eingriff mit dem Skalpell). Die Komplexität ist auch deutlich geringer. Auffallend sind zunächst die 4 "Kamine" - die Idee dahinter ist, Muttern einzulegen und diese mit dem oberen Gehäuseteil zu verschrauben. Das ganze ist (eher unbeabsichtigt) auf Pressung designed, sowohl für die Mutter, als auch in Richtung anderes Gehäuseteil. Immerhin rutscht nichts. An den Positionen der Taster befinden sich Sacklöcher/Kerben - aus einem sehr einfachen Grund: Material und Druckzeit sparen. Die Bodenplatte soll in weiten Teilen dick genug sein, dass sie stabil ist aber auf keinen Fall ein zweites Mal gedruckt werden muss. Um die Taster in der Höhe einzupassen, werden kleine Distanznippel eingesetzt, die klein sind und dadurch sehr schnell angepasst und gedruckt werden können. Weil ich keinen Sekundenkleber mehr da hatte, sind sie lediglich einseitig auf der Bodenplatte mit doppelseitigem Klebeband befestigt. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D-Modell der Bodenplatte anykeyx6_shim.png | Das 3D-Modell eines Nippel anykeyx6_bodenplatte_benippelt.jpg | Bodenplatte mit Muttern und Nippeln </gallery> Insgesamt war der Drucker etwa 4 Stunden beschäftigt, wobei er auch nicht mit maximaler Geschwindigkeit lief. Die Materialkosten liegen (ohne Probestücke und Fehldrucke) bei etwa 50 cent wenn ich mich nicht täusche, also nicht wirklich der Rede wert. =Zusammenbau= Ursprünglich habe ich einen Atmega8 im DIP-Gehäuse vorgesehen. Da es aber doch ein bisschen eng geworden wäre, kam dann doch einer im TQFP-Gehäuse zum Einsatz. Neben dem Mikrocontroller finden auch die 9 Transistoren für die LED-Ansteuerung Platz auf der Selfmade-Punktrasterplatine: <gallery> anykeyx6_platine.jpg | Bestückte Leiterkarte. </gallery> Die LED-Tasten bekommen gehörig lange Anschlussleitungen aus Kupferlackdraht, die durchgepiepst und auf passend beschriftete Klebebandstreifen landen. Miteinander verdrillt und verlötet kommen sie dann an die FETs. Gleiches Spiel für die Massen der Taster. <gallery> anykeyx6_tastenverdrahtung.jpg | Etwas Ordnung im Chaos </gallery> Damit die Tasten beim Zusammenfügen nicht immer wieder aus ihren Löchern entwischen, kommt Klebeband von außen auf das Gehäuse. Zur Sicherheit mit Nummern beschriftet, damit mit Drehen und Spiegeln nix schief geht. Tasten eingelegt, Leitungen im Gehäuse verlegt und den Kupfer-Knäuel zusammengedrückt. Papa sagte schon immer: Salat ist gesund. Das USB-Kabel liegt fest verzurrt und sehr engem Biegeradius im Gehäuse - hält (hoffentlich). <gallery> anykeyx6_boden_und_deckel.jpg | Beide Gehäusehälften anykeyx6_deckel_verklebt.jpg | Bestückungshilfe anykeyx6_deckel_assy.jpg | Deckel mit eingelegten Komponenten </gallery> In die untere Gehäusehälfte sind die Nippel schon eingeklebt und es wird spannend: passt es? Leider sind keine Senkkopfschrauben im Haus, also bleibt es mit den verzinkten Zylinderkopf-Schrauben etwas hässlich. Oder pragmatisch. Naja, es hält - und die Tasten liegen so im Gehäuse, dass sie weder (allzu sehr) klappern noch permanent gedrückt werden. Erfolg! :) Um bei den Tasten nicht im kompletten Blindflug zu sein, ziert noch ein Label und ein paar Symbole der FontAwesome die obere Reihe. Damit sollte nun nichts mehr schief geben. =Software= ==Erster Test== Die erste Testsoftware ist in Python geschrieben und lässt einen Regenbogen durchlaufen. Der Einfachheit halber fasst sie nur eine LED gleichzeitig an: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> Sieht dann als Momentaufnahme in etwa wie folgt aus: <gallery> anykeyx6_rgb_demo.jpg | Farben, yay! </gallery> ==Der OBS-Client== Ein "echtes" Plugin für OSB Studio zu schreiben spare ich mir mangels Tiefe in C++. Stattdessen nutze ich [https://github.com/Palakis/obs-websocket obs-websocket], das eine API für C# anbietet, die extrem einfach zu bedienen ist. Für die Buttons ist eine extrem rudimentäre Klasse sehr schnell zusammengehackt. Gänzlich ohne Fehlerbehandlung. Das Auslesen der Buttons erfolgt in einem Background-Worker, der Events feuert (und beim Loslassen zusätzlich die Dauer des Drückens ermittelt), das Setzen der LED-Farben erfolgt für alle 6. Hier merkt man auch wie heiß die Nadel ist mit der gestrickt wird: Zwischen dem Schreiben der beiden "Sets" legt sich die Software für eine Millisekunde schlafen. Der Grund einst einfach die dämlich - schreibt man zu schnell, geht evtl. das erste der beiden Datenpakete in der Firmware verloren, weil die Übergabe nicht (wenn man es so nennen will) threadsafe ist. Die GUI hat lediglich einen "Connect"-Button, der nur gedrückt werden sollte, wenn OBS läuft und die Hardware verbunden ist. Die Konfiguration ist ebenfalls eher grundlegend und in AnykeyOBS.exe.config zu finden. Hier kann für jede Taste die Aktiv/Inaktiv-Farbe als Hex-Code (oder named color, ungetestet) abgelegt werden, die Funktion definiert und ein Argument für diese Funktion angegeben werden. Zum Zuordnen einer Szene packt man in die Funktion "Scene" und schreibt den zugehörigen Szenen-Namen ins Argument. Für die Aufnahme heißt die Funktion "Record" und als Argument kann "Toggle", "Start" und "Stop" definiert werden. Streaming wird noch nicht unterstützt. Aus mir nicht ganz verständlichen Gründen kann der Zustand des Streamings/Recordings nur über Events ermittelt werden, dadurch bleibt die Taste mit entsprechender Zuordnung beim Start des Programms orange. Dies ist auch die (fest hinterlegte) Farbe für Übergänge zwischen Aufnahme und keine Aufnahme. Ein weiteres Feature ist das Abbrechen einer Funktion - Grundsätzlich werden die Aktionen erst beim Loslassen des Tasters getriggert - außer man drückt diesen länger als eine Sekunde. In diesem Fall wird die Aktion abgebrochen. Insgesamt kann man die Software allerhöchstens als Proof of Concept bezeichnen. Es funktioniert, irgendwie. ===Feuerprobe=== Mittlerweile durfte ich meine Schwester sogar besuchen, um ihr die Hardware zu geben. yay! Das Einrichten fand aber trotzdem online statt. obs-websockt installiert, AnykeyOBS aufs Tablet und: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Mist. Die vermutliche Ursache ist schnell gefunden: Bei manchen USB-Geräten kann der Name nicht gelesen werden. Eine Packung try-catch auf das Problem geworfen und eine Prise <code>Console.WriteLine</code>s und das Programm bleib nach dem Klick auf "Connect" geöffnet. "Leuchten die Knöppe?" - "Oh mann, wie geil" - "Also ja?". Danach hörte ich nur noch wildes Klicken. Ich glaube, das Teil gefällt. Und so sieht es aus: [[Datei:anykeyx6_demo.mp4]] =Fazit= Wo fange ich an? Beim Guten, beim Schlechten oder bei den Sachen, für die ich mich schäme? Unterm Strich: für eine sehr hemdsärmelig zusammengestrickte Hardware sieht es (ohne dass ich mich selbst loben möchte) ganz ordentlich aus. Schlimm wird es erst, wenn man unter die Haube schaut. Das dafür aber auch konsequent. Das Gute: * Meine Schwester hat etwas, das ihr hoffentlich die Arbeit etwas erleichtert * Ich habe wieder einiges in Sachen 3D-Druck gelernt * Es hat ziemlich viel Spaß gemacht * Alles ist bunt Das Schlechte: * Decoupling, welches Decoupling? * LEDs ** Nicht sonderlich hell ** Flackern bei USB-Traffic (durch INT0) ** In dunkler Umgebung zu hell und bei Tageslicht schlecht sichtbar * Das Setzen von LEDs und Tastendrücke können verschluckt werden * Taster ** Können auch von der Gehäuseunterseite betätigt werden ** Relativ laut (im Video hörbar) ** Wackeln, sind schief und haben keine Führung * Software ** An allen Ecken und Enden rudimentär, wenn etwas ausfällt, funktioniert erst einmal nichts ** Kein automatisches Verbinden mit OBS und der Hardware ** Keine GUI für die Konfiguration ** So gut wie keine Funktionen in OBS unterstützt ** Außer OBS-Steuerung keine weiteren Funktionen * Keine Standby-States =Downloads= * SketchUp-Dateien, zugehörige STLs, Firmware und C#-Software um mit OBS zu sprechen. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] 7e032baf482f7c963cede4b5c081b6304eb6b762 1578 1577 2020-05-10T18:17:31Z Chris 2 wikitext text/x-wiki [[Datei:anykeyx6_komplett.jpg|thumb|Fertig aufgebaute Hardware (Farben leicht retuschiert)]] Meine Schwester ist Lehrerin. Ein Job, um den ich sie nicht beneide - gerade in 2020. Hier in Bayern fängt (Stand Anfang Mai) das Leben an der Schule langsam wieder an, parallel zum Unterricht in den Schulen müssen jedoch die daheim bleibenden Kinder noch unterrichtet werden. Wenn man die eigene Arbeit ernst nimmt, ist das kein Spaß. Klar, man könnte für das Eigenstudium einfach Arbeitsblätter über den Zaun werfen und auf Seiten in den Büchern verweisen, aber wenn ich da an meine eigene Schulzeit und die eher extrinsische Motivation denke... Obwohl meine Schwester schon sehr viel digital hat, braucht Unterricht (gerade bei Sprachen) auch jemanden, der/die vor der Klasse spricht und natürlich ist eigenständiges Lernen für viele nicht ganz einfach. Aus diesem Grund hat meine Schwester angefangen, Videos zu machen. Vorerst nur mit ausgedruckten Blättern und dem Handy auf dem Stativ. Um Ihre digitalen Materialien besser nutzen zu können, fragte sie dann doch mal nach einem screen recorder. [https://obsproject.com/ OBS] war schnell installiert und eingerichtet. Blöd nur, dass sie keinen zweiten Monitor (bzw. Displayport-Adapter) für ihr MS Surface hat. Damit ihre Schüler sie auch mal sehen können (oder auch mal "Tafelunterricht" zu machen), habe ich ihr mehrere Szenen in OBS eingerichtet: * Bildschirmaufnahme * Bildschirmaufnahme + Kamera in der Ecke * Kamera Blöd ist nur, dass sie ohne besagten zweiten Bildschirm für jede Aktion OBS in den Vordergrund holen muss. Zwar kann man dort auch globale Hotkeys anlegen, aber ohne vollständige Tastatur läuft man sehr schnell Gefahr, Doppelbelegungen zu bekommen und dadurch sehr merkwürdiges Verhalten am PC zu haben. Gleichzeitig sieht man nicht, was OBS nun tatsächlich macht. Ja, man kann eine Fernbedienung für OBS auf dem Tablet oder Smartphone installieren, aber das schafft eigentlich nur mehr Probleme als es löst, zumal man die (freien) Clients, die ich auf Anhieb gefunden hab für jede Session neu konfigurieren muss. Zudem muss das Gerät am Laufen halten und kann die Tasten nicht erfühlen. Das lenkt unnötig ab und erhöht auch die Akzeptanz nicht wirklich. Auch fertige Lösungen wie das Elgato Stream Deck ist für die (hoffentlich) kurze Nutzungsdauer unverhältnismäßig teuer. Gleichzeitig sitzt hier ein Ingenieur herum, der aufgrund der aktuellen Situation erst einmal Gleitzeit abbaut. =Die Idee= Da kann man doch was basteln. Ein paar Taster, ein paar LEDs, ein bisschen Firmware und noch ein paar Zeilen Code auf dem PC. Was soll daran so aufwändig sein? Um eines vorweg zu nehmen: Übers Ziel hinausschießen, das kann daran aufwändig werden. Ziel ist, 6-8 bunt beleuchtete Taster zu haben, die in OBS eingebunden werden können. Der Mikrocontroller ist schnell gefunden. Um nicht zu weit von den Codebeispielen von [https://www.obdev.at/products/vusb/index-de.html V-USB] zu sein, soll ein oller ATmega8 zum Einsatz kommen. Weil ich schon länger was mit intelligenten LEDs machen wollte, liegt schon viel zu lange ein Streifen mit WS2812B herum. Der Plan war, diese – womöglich sogar noch auf dem Streifen – auf Taster zu kleben. Natürlich muss der [[wpde:Woman acceptance factor|WAF]] auch halbwegs passen, deshalb ist ein nicht zu schäbiges Gehäuse angesagt. 3D-Ducker sei dank bin ich auch dazu (zumindest seitens der Ausstattung) in der Lage. =Elektronik= Die Ernüchterung kam schneller als erwartet. Dass die Ansteuerung der LEDs zeitkritisch ist, wusste ich. Dass das auch für V-USB gilt, ebenfalls. Dass man beides nicht so einfach kombinieren kann, würde dann sehr schnell klar. Der USB-Stack braucht zwingend einen Pin-Interrupt, für die Ansteuerung der LEDs muss dieser aber abgeschaltet werden – sonst blinkt alles wie ein Weihnachtsbaum auf LSD. Tim (aka cpldcpu) hat sich die Mühe gemacht, V-USB mit [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling zu ermöglichen] - gleichzeitig sogar mit entsprechender LED. Den Weg wollte ich nicht gehen, weil das potenziell an anderen Stellen schmerzhaft werden könnte. Ok, was nun? Ein Coprozessor, der UART/I²C auf das LED-Protokoll umwandelt? Eigentlich wollte ich kein Mehrprozessor-System bauen – und auch hier bleibt das Problem mit Interrupts vs. keine Interrupts, auch durch die Einschränkungen durch USI dürfte das noch etwas unentspannter sein. Da ist guter Rat teuer. Auf einfarbige LEDs wollte ich aber auch nicht zurückgehen. ==LED-Treiber== 6 RGB-LEDs mit PWM anzusteuern, braucht es 18 PWM-Kanäle. Das hat glaube ich kein AVR8. ich habe zwar noch einen PCA9685 herumliegen, der aber auch nur 16 Kanäle bereitstellt. Zudem nimmt das Teil mit seinem Breakout-Board relativ viel Platz ein. Zu viel für das, was ich vor dem inneren Auge habe. Habe ich 18 Kanäle geschrieben? Jein. Betreibt man Multiplexing, reichen zwischen 3 und 6. Schlussendlich habe ich mich dafür entschieden, die Farben in den Multiplex zu nehmen und den PWM pro Taste laufen zu lassen - mit entsprechenden Einbußen der Helligkeit (ein Drittel). Aber wo bekommt man an einem ATmega8 6 synchrone PWM-Kanäle her? Ganz einfach: gar nicht. Zumindest in Hardware - anders schaut es in Software aus, wo es auch keine richtige PWM ist, sondern eher eine Pulsleistungsmodulation (kurz PDM - einen passenden Begriff konnte ich finden, daher die Neukreation), wie sie 2011 auf der [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite] schon beschrieben wurde. Um es kurz zu beschreiben: bei gewöhnlicher PWM gibt es für jeden Kanal zwei Schaltzeitpunkte, von denen einer pro Kanal individuell ist (da er den Helligkeitswert vorgibt). Hat man n Kanäle, gibt es n Zeitpunkte, die man möglichst zielgenau treffen muss. Gerade wenn diese nah beieinander liegen, kann das zu Timingproblemen führen. Der hier verwendete Dimmer funktioniert anders. Man muss dabei bedenken, dass es beim Dimmen von LEDs relativ egal ist, ob sie über einen Zyklus am Stück an sind, oder ob sie zwischendurch ausgeschaltet werden können - wichtig ist unterm Strich nur, wie viel sie im im Laufe eines Zyklus aktiv sind. Bei einer Auflösung von b bit gibt es bei dieser Methode b Zeitpunkte - ganz egal wie viele Kanäle man verwendet und: deren Timing ist fest. Zudem sind diese sind zeitlich immer mit Faktor 2 voneinander getrennt. Nun schaltet man den Kanal immer dann an, wenn im Helligkeitswert das "Bit" des zugehörigen Zeitschlitzes aktiv ist. Da es visuell deutlich besser als mit Text funktioniert, hier mal zwei Beispiele mit einer Modulation mit 3 Bit. Die Wertigkeit steht links, die An-Zeiten entsprechen den grünen Blöcken (deren X-Achse der Zeit entspricht) und die nötigen Interrupts sind mit roten Pfeilen markiert: <gallery> anykeyx6_pwm.png | Pulsweitenmodulation anykeyx6_plm.png | Pulsleistungsmodulation </gallery> Betrachtet man die aktive Fläche der einzelnen Helligkeitswerte, kommt man auf das gleiche - nur dass die PDM deutlich ressourcenschonender ist. Dazu kommt der Effekt, dass durch das "Zerhacken" der PWM die LEDs mit einer höheren Frequenz flackern (auch wenn sie variiert). Dadurch wird der Stroboskop-Effekt verringert - des einen Freud ist des anderen Leid: achtet man auf EMV, wird es and er Stelle unangenehmer. Aber genug dazu. Aufgrund des Multiplexing gibt es, wie oben beschrieben, nur ein Drittel an Helligkeit. Die meisten LEDs halten bei pulsförmiger Ansteuerung deutlich mehr Strom als im Dauerbetrieb aus weil der limitierende Faktor die Erwärmung ist. Da die LEDs (im 5050-Gehäuse) für den Aufbau von einem LED-Streifen "geerntet" wurden, habe ich kein Datenblatt zur Komponente, aber Wissen: z. B. kommt für den roten Strang ein 330 Ohm-Widerstand zum Einsatz, bei 12 V und 3 roten LEDs in Reihe mit ca. 1,85 V Vorwärtsspannung sind das etwa 20 mA. Ohne weitere Infos zu maximalen Strömen und weil die Helligkeit eigentlich reichen sollte, bin ich bei diesem Strom geblieben. ==Taster== Die Taster kommen direkt an IOs und sind gegen Masse verschaltet. Eine rudimentäre Entprellung wird in Software gemacht. ==USB== Die USB-Beschaltung entspricht weitestgehend der aus den Beispielen von Objective Development. Aus reiner Faulheit habe ich die Schutzbeschaltung vom [[USB-Fußtaster]] übernommen. Sprichwörtlich: Die nötigen Bauteile bestückt und die Leiterkarte auf die passende Größe gestutzt. ==Schaltplan== Die gesamte Schaltung ist also relativ einfach. Als FETs für die LEDs kommen BSS84 (p-Kanal, aufseiten der Anoden) und BSS138 (n-Kanal, aufseiten der Kathoden) zum Einsatz. Aufgrund der Komplexität reicht es als Handskizze: <gallery> anykeyx6_sch.png | Schaltplan - unbekannter Künstler, 2020, digital </gallery> =Firmware= Die Firmware ist erstaunlich einfach, zumal ich mich nicht sonderlich bemüht habe. Die LEDs werden mit der oben beschriebenen Methode (in leddrv.c) angesteuert, wobei zusätzlich noch eine Fading-Funktion zum Einsatz kommt. Das entlastet den USB-Stack und verringert das Flackern (siehe weiter unten) Die Tasten werden (sofern die PWM nicht höhere Priorität hat) jede Millisekunde abgefragt (<code>buttons_tick()</code>) und wenn der Pegel low (Taste gedrückt) ist, ein Zähler inkrementiert. Bei High-Pegel wird der Zähler auf 0 zurückgesetzt. Ist der Zähler größer als 10, gilt die entsprechende Taste gedrückt. Alle Buttons in einem Byte können über die Methode <code>buttons_values()</code> abgefragt werden. In Sachen USB wird ein Out-Report (PC -> Device) mit Netto 16 Byte und ein In-Report mit Netto 8 Byte (Device -> PC) verwendet. Der Out-Report dient zum Setzen der LEDs und sieht wie folgt aus: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index der LED (1-6) * <span class="hb2">Rx</span>: Rot-Wert der LED (0 ... 255) * <span class="hb3">Gx</span>: Grün-Wert der LED (0 ... 255) * <span class="hb4">Bx</span>: Blau-Wert der LED (0 ... 255) * <span class="hb5">Tx</span>: Dauer für den Übergang (0 ... 255, in 5 ms-Schritten) Es können somit 3 Farben gleichzeitig geschrieben werden, Index 0 wird nicht verwendet, da es üblicherweise der Init-Wert für Arrays ist und somit nicht versehentlich die Farbe einer Taste gesetzt wird. Der In-Report ist denkbar einfach, im ersten Byte steht das Bit-Muster der aktuell gedrückten Taster: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> Der Report wird bei jeder Änderung des Zustands der Taster gesendet. Das ist in mehrerlei Hinsicht nicht ganz ideal, da zum einen der Initiale Zustand (nach Öffnen des Devices) nicht ermittelt werden kann und falls doch mal ein USB-Paket verloren geht, verpasst man Tastendrücke. Aber: es musste schnell gehen. =Mechanik= Die Mechanik ist (zumindest für mich als Neuling in Sachen Design und 3D-Druck) ein Stück aufwändiger. Einfach nur die Leiterkarte auf den Tisch zu knallen geht hier nicht, es muss nicht wie aus dem Ei gepellt aussehen, aber nicht nur aus der Kategorie "form follows function" sein. Um schnell voran zu kommen, kam das MS Paint im 3D-Design zum Einsatz: SketchUp. Mit allen Einschränkungen und fehlender Parametrisierung bin ich darin leider noch immer am schnellsten, etwas für den Druck vorzubereiten. ==Tasten== Mit ein bisschen Zeichnen in 2D-Software stellte sich heraus, dass rechteckige Tasten mit 15 mm Breite und Höhe, einer Abrundung mit Radius 2,5 mm und einem Abstand von 5 mm zueinander eine angenehme Haptik aufweisen. Ein erstes Muster mit Kragen (damit die Taste nicht durchs Gehäuse fällt) ist schnell gedruckt - mit transparentem PLA, (wenn ich mich richtig erinnere) 50 % Infill und konzentrischem Top/Bottom-Pattern (in Cura gesliced) ist schnell gedruckt und sieht, nachdem er mit Farbe beschmiert wurde um zu sehen wie dicht der Druck ist auch nach dem Reinigen versaut aus. Licht geht durch, sieht aber eher bescheiden aus: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Ausleuchtung bei konzentrischem Druck </gallery> Als nächstes kommt die Frage: wie die LEDs und Taster montieren? um das mechanische Design zu vereinfachen, habe ich die Idee verfolgt, möglichst Gleichteile zu verwenden. In meinen letzten Leiterkarten-Bestellungen habe ich im Waste immer 1x1 mm Kupferflächen im 1,27 mm-Raster platziert, ein Streifen damit ist etwa 9,6 mm breit (bei 1,6 mm Materialdicke) - eine gute Größe für diese Anwendung. LED auf die eine Seite, Taster auf die andere und eine Idee, für die mich die Mechaniker in der Arbeit (völlig zu Recht) vermutlich nicht mehr anschauen würden: Constraining auf zwei Bezugsebenen. Normalerweise strebt man an, dass sich die Toleranzen von einer Seite aus ausbreiten, damit man die Toleranzketten in Griff halten kann. Würde hier heißen: Die Tasten sind auf die Gehäusefront referenziert und dementsprechend müssen die Taster auch an einer Ebene montiert werden, deren Toleranz sich auf die Front bezieht. Bei mir sollen die Taster aber gegen die Bodenplatte drücken. Mit vielen Nachteilen. Da es sich aktuell allerdings um ein Einzelstück handelt: Egal. Das Platinchen mit LED vorne und Taster hinten wird einfach in eine Nut im Taster eingeschoben. Bis auf einen kleinen (reproduzierbaren) Druckfehler funktioniert das prächtig. Hier die verschiedenen Designiterationen: <gallery> anykeyx6_taste_iterationen.jpg | Iterationen der Tasten 1 bis 5.5 anykeyx6_sketchup_taste_seite.png | Finales Modell der Tasten von der Seite anykeyx6_sketchup_taster_unten.png | und von unten anykeyx6_taste_einzelteile.jpg | Einzelteile der Tasten (der Taster fehlt) anykeyx6_taste_LED.jpg | Leiterkarte in die Taste eingeschoben </gallery> Mit Infill auf 100 % und der Tasterfront auf dem Druckbett entsteht eine relativ schöne Oberfläche. Da Concentric Top/Bottom-Pattern ein Kreuz in der Diagonale erzeugt hat, bin ich auf "Lines" umgestiegen, das die Taster, gemeinsam mit dem konzentrischen Rahmen fast schon "wie gekauft" aussehen lässt. Um eine bessere Farbmischung zu erzeugen (und die Taster eine eigenwillige Streuwirkung haben), habe ich etwas Band aus meinem Beschriftungsgerät (Wenn es wichtig ist: Brother P-touch) hinter den Taster geklebt. Dadurch wird die Ausleuchtung der drei LED-Kristalle zumindest ein bisschen homogener: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Zum Vergleich nochmal das Bild von oben (konzentrischer Druck) anykeyx6_beleuchtung_diffusor.jpg | links ohne Folie, rechts mit </gallery> Insgesamt hat das Sandwich eine Höhe von 12,4 mm - 0,25 mm weniger, wenn der Taster gedrückt ist. Der Kragen ist 2,5 mm nach innen versetzt. Das, plus die Dicke der Gehäuseteile, wird die Gesamtdicke des Geräts. =Gehäuse= Mit den Maßen der Tasten geht es los, wobei die Ausschnitte für diese um 0,25 mm in alle Richtungen erweitert wurden. Das bringt zwar etwas Spiel, aber bevor der Cutter angesetzt oder nochmals gedruckt werden muss, dürfen die Tasten eher ein bisschen wackeln - zumal es bei den ersten Tastern ordentlich Elefantenfüße gab. Mit einem Überstand von 7,5 mm von der Kante der Taster zu den Gehäusewänden in drei Richtungen und etwas mehr (17,5 mm) in die vierte Richtung - irgendwo muss ja die Elektronik hin - ist das Gehäuse relativ kompakt. Im inneren befinden sich zwischen den Tastern 4 mm hohe Wände - nicht zum Ausrichten, sondern vielmehr um Streulicht zwischen den Tastern zu vermeiden. Damit sich das Gehäuse nicht durchbiegt und dadurch versehentlich mehrere Taster auf einmal betätigt werden, befinden sich in den Kreuzungspunkten der Taster Erhöhungen, die die Stabilität in Z-Richtung erhöhen. Um Material und vor allem Druckzeit zu sparen, gab es zwei abgeschnittene Druckmuster, die man dank transparentem Filament auf weißem Grund fast nicht sieht: <gallery> anykeyx6_druckmuster_deckel.jpg | Druckmuster für die Aufnahme der Tasten </gallery> Als Zugentlastung des fest installierten USB-Kabels befindet sich hinter dem U-förmigen Ausschnitt eine kleine Rampe und ein Loch, durch den ein Kabelbinder passt. Die Rampe dient lediglich dazu, dass der Kabelbinder die untere Gehäusehälfte nicht nach unten drückt. Man könnte mutmaßen, dass durch die Druckschichten bedingte Treppenstruktur die Leitung sogar ein bisschen verhakt wird. 3 Löcher, durch die M2,5-Schrauben passen, dienen zur Befestigung der Bodenplatte. Insgesamt gab es 4 Iterationen, wobei nur zwei den Weg auf den Drucker gefunden haben - und das auch nur, weil sich das erste Druckteil vom Druckbett abgelöst und dadurch unschön verzogen hat. Anscheinend sind die STL-Daten nicht ganz sauber, wodurch das Modell wohl etwas in der Luft hängt. Durch einen Microstep von -0,001 in Z-Richtung wurde das Druckergebnis besser, aber die erste Lage ist trotzdem noch etwas lückig... <gallery> anykeyx6_sketchup_deckel.png | 3D-Modell des Deckels anykeyx6_deckel_vergurkt.jpg | Der erste Versuch (vergurkt) anykeyx6_Deckel.jpg | Der bessere Druck. </gallery> Das untere Gehäuseteil sind eigentlich 7 Teile und brauchte keine Revision (aber einen kleinen Eingriff mit dem Skalpell). Die Komplexität ist auch deutlich geringer. Auffallend sind zunächst die 4 "Kamine" - die Idee dahinter ist, Muttern einzulegen und diese mit dem oberen Gehäuseteil zu verschrauben. Das ganze ist (eher unbeabsichtigt) auf Pressung designed, sowohl für die Mutter, als auch in Richtung anderes Gehäuseteil. Immerhin rutscht nichts. An den Positionen der Taster befinden sich Sacklöcher/Kerben - aus einem sehr einfachen Grund: Material und Druckzeit sparen. Die Bodenplatte soll in weiten Teilen dick genug sein, dass sie stabil ist aber auf keinen Fall ein zweites Mal gedruckt werden muss. Um die Taster in der Höhe einzupassen, werden kleine Distanznippel eingesetzt, die klein sind und dadurch sehr schnell angepasst und gedruckt werden können. Weil ich keinen Sekundenkleber mehr da hatte, sind sie lediglich einseitig auf der Bodenplatte mit doppelseitigem Klebeband befestigt. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D-Modell der Bodenplatte anykeyx6_shim.png | Das 3D-Modell eines Nippel anykeyx6_bodenplatte_benippelt.jpg | Bodenplatte mit Muttern und Nippeln </gallery> Insgesamt war der Drucker etwa 4 Stunden beschäftigt, wobei er auch nicht mit maximaler Geschwindigkeit lief. Die Materialkosten liegen (ohne Probestücke und Fehldrucke) bei etwa 50 cent wenn ich mich nicht täusche, also nicht wirklich der Rede wert. =Zusammenbau= Ursprünglich habe ich einen Atmega8 im DIP-Gehäuse vorgesehen. Da es aber doch ein bisschen eng geworden wäre, kam dann doch einer im TQFP-Gehäuse zum Einsatz. Neben dem Mikrocontroller finden auch die 9 Transistoren für die LED-Ansteuerung Platz auf der Selfmade-Punktrasterplatine: <gallery> anykeyx6_platine.jpg | Bestückte Leiterkarte. </gallery> Die LED-Tasten bekommen gehörig lange Anschlussleitungen aus Kupferlackdraht, die durchgepiepst und auf passend beschriftete Klebebandstreifen landen. Miteinander verdrillt und verlötet kommen sie dann an die FETs. Gleiches Spiel für die Massen der Taster. <gallery> anykeyx6_tastenverdrahtung.jpg | Etwas Ordnung im Chaos </gallery> Damit die Tasten beim Zusammenfügen nicht immer wieder aus ihren Löchern entwischen, kommt Klebeband von außen auf das Gehäuse. Zur Sicherheit mit Nummern beschriftet, damit mit Drehen und Spiegeln nix schief geht. Tasten eingelegt, Leitungen im Gehäuse verlegt und den Kupfer-Knäuel zusammengedrückt. Papa sagte schon immer: Salat ist gesund. Das USB-Kabel liegt fest verzurrt und sehr engem Biegeradius im Gehäuse - hält (hoffentlich). <gallery> anykeyx6_boden_und_deckel.jpg | Beide Gehäusehälften anykeyx6_deckel_verklebt.jpg | Bestückungshilfe anykeyx6_deckel_assy.jpg | Deckel mit eingelegten Komponenten </gallery> In die untere Gehäusehälfte sind die Nippel schon eingeklebt und es wird spannend: passt es? Leider sind keine Senkkopfschrauben im Haus, also bleibt es mit den verzinkten Zylinderkopf-Schrauben etwas hässlich. Oder pragmatisch. Naja, es hält - und die Tasten liegen so im Gehäuse, dass sie weder (allzu sehr) klappern noch permanent gedrückt werden. Erfolg! :) Um bei den Tasten nicht im kompletten Blindflug zu sein, ziert noch ein Label und ein paar Symbole der FontAwesome die obere Reihe. Damit sollte nun nichts mehr schief geben. =Software= ==Erster Test== Die erste Testsoftware ist in Python geschrieben und lässt einen Regenbogen durchlaufen. Der Einfachheit halber fasst sie nur eine LED gleichzeitig an: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> Sieht dann als Momentaufnahme in etwa wie folgt aus: <gallery> anykeyx6_rgb_demo.jpg | Farben, yay! </gallery> ==Der OBS-Client== Ein "echtes" Plugin für OSB Studio zu schreiben spare ich mir mangels Tiefe in C++. Stattdessen nutze ich [https://github.com/Palakis/obs-websocket obs-websocket], das eine API für C# anbietet, die extrem einfach zu bedienen ist. Für die Buttons ist eine extrem rudimentäre Klasse sehr schnell zusammengehackt. Gänzlich ohne Fehlerbehandlung. Das Auslesen der Buttons erfolgt in einem Background-Worker, der Events feuert (und beim Loslassen zusätzlich die Dauer des Drückens ermittelt), das Setzen der LED-Farben erfolgt für alle 6. Hier merkt man auch wie heiß die Nadel ist mit der gestrickt wird: Zwischen dem Schreiben der beiden "Sets" legt sich die Software für eine Millisekunde schlafen. Der Grund einst einfach die dämlich - schreibt man zu schnell, geht evtl. das erste der beiden Datenpakete in der Firmware verloren, weil die Übergabe nicht (wenn man es so nennen will) threadsafe ist. Die GUI hat lediglich einen "Connect"-Button, der nur gedrückt werden sollte, wenn OBS läuft und die Hardware verbunden ist. Die Konfiguration ist ebenfalls eher grundlegend und in AnykeyOBS.exe.config zu finden. Hier kann für jede Taste die Aktiv/Inaktiv-Farbe als Hex-Code (oder named color, ungetestet) abgelegt werden, die Funktion definiert und ein Argument für diese Funktion angegeben werden. Zum Zuordnen einer Szene packt man in die Funktion "Scene" und schreibt den zugehörigen Szenen-Namen ins Argument. Für die Aufnahme heißt die Funktion "Record" und als Argument kann "Toggle", "Start" und "Stop" definiert werden. Streaming wird noch nicht unterstützt. Aus mir nicht ganz verständlichen Gründen kann der Zustand des Streamings/Recordings nur über Events ermittelt werden, dadurch bleibt die Taste mit entsprechender Zuordnung beim Start des Programms orange. Dies ist auch die (fest hinterlegte) Farbe für Übergänge zwischen Aufnahme und keine Aufnahme. Ein weiteres Feature ist das Abbrechen einer Funktion - Grundsätzlich werden die Aktionen erst beim Loslassen des Tasters getriggert - außer man drückt diesen länger als eine Sekunde. In diesem Fall wird die Aktion abgebrochen. Insgesamt kann man die Software allerhöchstens als Proof of Concept bezeichnen. Es funktioniert, irgendwie. ===Feuerprobe=== Mittlerweile durfte ich meine Schwester sogar besuchen, um ihr die Hardware zu geben. yay! Das Einrichten fand aber trotzdem online statt. obs-websockt installiert, AnykeyOBS aufs Tablet und: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Mist. Die vermutliche Ursache ist schnell gefunden: Bei manchen USB-Geräten kann der Name nicht gelesen werden. Eine Packung try-catch auf das Problem geworfen und eine Prise <code>Console.WriteLine</code>s und das Programm bleib nach dem Klick auf "Connect" geöffnet. "Leuchten die Knöppe?" - "Oh mann, wie geil" - "Also ja?". Danach hörte ich nur noch wildes Klicken. Ich glaube, das Teil gefällt. Und so sieht es aus: [[Datei:anykeyx6_demo.mp4]] =Fazit= Wo fange ich an? Beim Guten, beim Schlechten oder bei den Sachen, für die ich mich schäme? Unterm Strich: für eine sehr hemdsärmelig zusammengestrickte Hardware sieht es (ohne dass ich mich selbst loben möchte) ganz ordentlich aus. Schlimm wird es erst, wenn man unter die Haube schaut. Das dafür aber auch konsequent. Das Gute: * Meine Schwester hat etwas, das ihr hoffentlich die Arbeit etwas erleichtert * Ich habe wieder einiges in Sachen 3D-Druck gelernt * Es hat ziemlich viel Spaß gemacht * Alles ist bunt Das Schlechte: * Decoupling, welches Decoupling? * LEDs ** Nicht sonderlich hell ** Flackern bei USB-Traffic (durch INT0) ** In dunkler Umgebung zu hell und bei Tageslicht schlecht sichtbar * Das Setzen von LEDs und Tastendrücke können verschluckt werden * Taster ** Können auch von der Gehäuseunterseite betätigt werden ** Relativ laut (im Video hörbar) ** Wackeln, sind schief und haben keine Führung * Software ** An allen Ecken und Enden rudimentär, wenn etwas ausfällt, funktioniert erst einmal nichts ** Kein automatisches Verbinden mit OBS und der Hardware ** Keine GUI für die Konfiguration ** So gut wie keine Funktionen in OBS unterstützt ** Außer OBS-Steuerung keine weiteren Funktionen * Keine Standby-States =Downloads= * SketchUp-Dateien, zugehörige STLs, Firmware und C#-Software um mit OBS zu sprechen. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] dec024c50303397974f70c1ece24082399545409 1580 1578 2020-05-10T19:55:07Z Chris 2 Typo wikitext text/x-wiki [[Datei:anykeyx6_komplett.jpg|thumb|Fertig aufgebaute Hardware (Farben leicht retuschiert)]] Meine Schwester ist Lehrerin. Ein Job, um den ich sie nicht beneide - gerade in 2020. Hier in Bayern fängt (Stand Anfang Mai) das Leben an der Schule langsam wieder an, parallel zum Unterricht in den Schulen müssen jedoch die daheim bleibenden Kinder noch unterrichtet werden. Wenn man die eigene Arbeit ernst nimmt, ist das kein Spaß. Klar, man könnte für das Eigenstudium einfach Arbeitsblätter über den Zaun werfen und auf Seiten in den Büchern verweisen, aber wenn ich da an meine eigene Schulzeit und die eher extrinsische Motivation denke... Obwohl meine Schwester schon sehr viel digital hat, braucht Unterricht (gerade bei Sprachen) auch jemanden, der/die vor der Klasse spricht und natürlich ist eigenständiges Lernen für viele nicht ganz einfach. Aus diesem Grund hat meine Schwester angefangen, Videos zu machen. Vorerst nur mit ausgedruckten Blättern und dem Handy auf dem Stativ. Um Ihre digitalen Materialien besser nutzen zu können, fragte sie dann doch mal nach einem screen recorder. [https://obsproject.com/ OBS] war schnell installiert und eingerichtet. Blöd nur, dass sie keinen zweiten Monitor (bzw. Displayport-Adapter) für ihr MS Surface hat. Damit ihre Schüler sie auch mal sehen können (oder auch mal "Tafelunterricht" zu machen), habe ich ihr mehrere Szenen in OBS eingerichtet: * Bildschirmaufnahme * Bildschirmaufnahme + Kamera in der Ecke * Kamera Blöd ist nur, dass sie ohne besagten zweiten Bildschirm für jede Aktion OBS in den Vordergrund holen muss. Zwar kann man dort auch globale Hotkeys anlegen, aber ohne vollständige Tastatur läuft man sehr schnell Gefahr, Doppelbelegungen zu bekommen und dadurch sehr merkwürdiges Verhalten am PC zu haben. Gleichzeitig sieht man nicht, was OBS nun tatsächlich macht. Ja, man kann eine Fernbedienung für OBS auf dem Tablet oder Smartphone installieren, aber das schafft eigentlich nur mehr Probleme als es löst, zumal man die (freien) Clients, die ich auf Anhieb gefunden hab für jede Session neu konfigurieren muss. Zudem muss das Gerät am Laufen halten und kann die Tasten nicht erfühlen. Das lenkt unnötig ab und erhöht auch die Akzeptanz nicht wirklich. Auch fertige Lösungen wie das Elgato Stream Deck ist für die (hoffentlich) kurze Nutzungsdauer unverhältnismäßig teuer. Gleichzeitig sitzt hier ein Ingenieur herum, der aufgrund der aktuellen Situation erst einmal Gleitzeit abbaut. =Die Idee= Da kann man doch was basteln. Ein paar Taster, ein paar LEDs, ein bisschen Firmware und noch ein paar Zeilen Code auf dem PC. Was soll daran so aufwändig sein? Um eines vorweg zu nehmen: Übers Ziel hinausschießen, das kann daran aufwändig werden. Ziel ist, 6-8 bunt beleuchtete Taster zu haben, die in OBS eingebunden werden können. Der Mikrocontroller ist schnell gefunden. Um nicht zu weit von den Codebeispielen von [https://www.obdev.at/products/vusb/index-de.html V-USB] zu sein, soll ein oller ATmega8 zum Einsatz kommen. Weil ich schon länger was mit intelligenten LEDs machen wollte, liegt schon viel zu lange ein Streifen mit WS2812B herum. Der Plan war, diese – womöglich sogar noch auf dem Streifen – auf Taster zu kleben. Natürlich muss der [[wpde:Woman acceptance factor|WAF]] auch halbwegs passen, deshalb ist ein nicht zu schäbiges Gehäuse angesagt. 3D-Drucker sei dank bin ich auch dazu (zumindest seitens der Ausstattung) in der Lage. =Elektronik= Die Ernüchterung kam schneller als erwartet. Dass die Ansteuerung der LEDs zeitkritisch ist, wusste ich. Dass das auch für V-USB gilt, ebenfalls. Dass man beides nicht so einfach kombinieren kann, würde dann sehr schnell klar. Der USB-Stack braucht zwingend einen Pin-Interrupt, für die Ansteuerung der LEDs muss dieser aber abgeschaltet werden – sonst blinkt alles wie ein Weihnachtsbaum auf LSD. Tim (aka cpldcpu) hat sich die Mühe gemacht, V-USB mit [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling zu ermöglichen] - gleichzeitig sogar mit entsprechender LED. Den Weg wollte ich nicht gehen, weil das potenziell an anderen Stellen schmerzhaft werden könnte. Ok, was nun? Ein Coprozessor, der UART/I²C auf das LED-Protokoll umwandelt? Eigentlich wollte ich kein Mehrprozessor-System bauen – und auch hier bleibt das Problem mit Interrupts vs. keine Interrupts, auch durch die Einschränkungen durch USI dürfte das noch etwas unentspannter sein. Da ist guter Rat teuer. Auf einfarbige LEDs wollte ich aber auch nicht zurückgehen. ==LED-Treiber== 6 RGB-LEDs mit PWM anzusteuern, braucht es 18 PWM-Kanäle. Das hat glaube ich kein AVR8. ich habe zwar noch einen PCA9685 herumliegen, der aber auch nur 16 Kanäle bereitstellt. Zudem nimmt das Teil mit seinem Breakout-Board relativ viel Platz ein. Zu viel für das, was ich vor dem inneren Auge habe. Habe ich 18 Kanäle geschrieben? Jein. Betreibt man Multiplexing, reichen zwischen 3 und 6. Schlussendlich habe ich mich dafür entschieden, die Farben in den Multiplex zu nehmen und den PWM pro Taste laufen zu lassen - mit entsprechenden Einbußen der Helligkeit (ein Drittel). Aber wo bekommt man an einem ATmega8 6 synchrone PWM-Kanäle her? Ganz einfach: gar nicht. Zumindest in Hardware - anders schaut es in Software aus, wo es auch keine richtige PWM ist, sondern eher eine Pulsleistungsmodulation (kurz PDM - einen passenden Begriff konnte ich finden, daher die Neukreation), wie sie 2011 auf der [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite] schon beschrieben wurde. Um es kurz zu beschreiben: bei gewöhnlicher PWM gibt es für jeden Kanal zwei Schaltzeitpunkte, von denen einer pro Kanal individuell ist (da er den Helligkeitswert vorgibt). Hat man n Kanäle, gibt es n Zeitpunkte, die man möglichst zielgenau treffen muss. Gerade wenn diese nah beieinander liegen, kann das zu Timingproblemen führen. Der hier verwendete Dimmer funktioniert anders. Man muss dabei bedenken, dass es beim Dimmen von LEDs relativ egal ist, ob sie über einen Zyklus am Stück an sind, oder ob sie zwischendurch ausgeschaltet werden können - wichtig ist unterm Strich nur, wie viel sie im im Laufe eines Zyklus aktiv sind. Bei einer Auflösung von b bit gibt es bei dieser Methode b Zeitpunkte - ganz egal wie viele Kanäle man verwendet und: deren Timing ist fest. Zudem sind diese sind zeitlich immer mit Faktor 2 voneinander getrennt. Nun schaltet man den Kanal immer dann an, wenn im Helligkeitswert das "Bit" des zugehörigen Zeitschlitzes aktiv ist. Da es visuell deutlich besser als mit Text funktioniert, hier mal zwei Beispiele mit einer Modulation mit 3 Bit. Die Wertigkeit steht links, die An-Zeiten entsprechen den grünen Blöcken (deren X-Achse der Zeit entspricht) und die nötigen Interrupts sind mit roten Pfeilen markiert: <gallery> anykeyx6_pwm.png | Pulsweitenmodulation anykeyx6_plm.png | Pulsleistungsmodulation </gallery> Betrachtet man die aktive Fläche der einzelnen Helligkeitswerte, kommt man auf das gleiche - nur dass die PDM deutlich ressourcenschonender ist. Dazu kommt der Effekt, dass durch das "Zerhacken" der PWM die LEDs mit einer höheren Frequenz flackern (auch wenn sie variiert). Dadurch wird der Stroboskop-Effekt verringert - des einen Freud ist des anderen Leid: achtet man auf EMV, wird es and er Stelle unangenehmer. Aber genug dazu. Aufgrund des Multiplexing gibt es, wie oben beschrieben, nur ein Drittel an Helligkeit. Die meisten LEDs halten bei pulsförmiger Ansteuerung deutlich mehr Strom als im Dauerbetrieb aus weil der limitierende Faktor die Erwärmung ist. Da die LEDs (im 5050-Gehäuse) für den Aufbau von einem LED-Streifen "geerntet" wurden, habe ich kein Datenblatt zur Komponente, aber Wissen: z. B. kommt für den roten Strang ein 330 Ohm-Widerstand zum Einsatz, bei 12 V und 3 roten LEDs in Reihe mit ca. 1,85 V Vorwärtsspannung sind das etwa 20 mA. Ohne weitere Infos zu maximalen Strömen und weil die Helligkeit eigentlich reichen sollte, bin ich bei diesem Strom geblieben. ==Taster== Die Taster kommen direkt an IOs und sind gegen Masse verschaltet. Eine rudimentäre Entprellung wird in Software gemacht. ==USB== Die USB-Beschaltung entspricht weitestgehend der aus den Beispielen von Objective Development. Aus reiner Faulheit habe ich die Schutzbeschaltung vom [[USB-Fußtaster]] übernommen. Sprichwörtlich: Die nötigen Bauteile bestückt und die Leiterkarte auf die passende Größe gestutzt. ==Schaltplan== Die gesamte Schaltung ist also relativ einfach. Als FETs für die LEDs kommen BSS84 (p-Kanal, aufseiten der Anoden) und BSS138 (n-Kanal, aufseiten der Kathoden) zum Einsatz. Aufgrund der Komplexität reicht es als Handskizze: <gallery> anykeyx6_sch.png | Schaltplan - unbekannter Künstler, 2020, digital </gallery> =Firmware= Die Firmware ist erstaunlich einfach, zumal ich mich nicht sonderlich bemüht habe. Die LEDs werden mit der oben beschriebenen Methode (in leddrv.c) angesteuert, wobei zusätzlich noch eine Fading-Funktion zum Einsatz kommt. Das entlastet den USB-Stack und verringert das Flackern (siehe weiter unten) Die Tasten werden (sofern die PWM nicht höhere Priorität hat) jede Millisekunde abgefragt (<code>buttons_tick()</code>) und wenn der Pegel low (Taste gedrückt) ist, ein Zähler inkrementiert. Bei High-Pegel wird der Zähler auf 0 zurückgesetzt. Ist der Zähler größer als 10, gilt die entsprechende Taste gedrückt. Alle Buttons in einem Byte können über die Methode <code>buttons_values()</code> abgefragt werden. In Sachen USB wird ein Out-Report (PC -> Device) mit Netto 16 Byte und ein In-Report mit Netto 8 Byte (Device -> PC) verwendet. Der Out-Report dient zum Setzen der LEDs und sieht wie folgt aus: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index der LED (1-6) * <span class="hb2">Rx</span>: Rot-Wert der LED (0 ... 255) * <span class="hb3">Gx</span>: Grün-Wert der LED (0 ... 255) * <span class="hb4">Bx</span>: Blau-Wert der LED (0 ... 255) * <span class="hb5">Tx</span>: Dauer für den Übergang (0 ... 255, in 5 ms-Schritten) Es können somit 3 Farben gleichzeitig geschrieben werden, Index 0 wird nicht verwendet, da es üblicherweise der Init-Wert für Arrays ist und somit nicht versehentlich die Farbe einer Taste gesetzt wird. Der In-Report ist denkbar einfach, im ersten Byte steht das Bit-Muster der aktuell gedrückten Taster: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> Der Report wird bei jeder Änderung des Zustands der Taster gesendet. Das ist in mehrerlei Hinsicht nicht ganz ideal, da zum einen der Initiale Zustand (nach Öffnen des Devices) nicht ermittelt werden kann und falls doch mal ein USB-Paket verloren geht, verpasst man Tastendrücke. Aber: es musste schnell gehen. =Mechanik= Die Mechanik ist (zumindest für mich als Neuling in Sachen Design und 3D-Druck) ein Stück aufwändiger. Einfach nur die Leiterkarte auf den Tisch zu knallen geht hier nicht, es muss nicht wie aus dem Ei gepellt aussehen, aber nicht nur aus der Kategorie "form follows function" sein. Um schnell voran zu kommen, kam das MS Paint im 3D-Design zum Einsatz: SketchUp. Mit allen Einschränkungen und fehlender Parametrisierung bin ich darin leider noch immer am schnellsten, etwas für den Druck vorzubereiten. ==Tasten== Mit ein bisschen Zeichnen in 2D-Software stellte sich heraus, dass rechteckige Tasten mit 15 mm Breite und Höhe, einer Abrundung mit Radius 2,5 mm und einem Abstand von 5 mm zueinander eine angenehme Haptik aufweisen. Ein erstes Muster mit Kragen (damit die Taste nicht durchs Gehäuse fällt) ist schnell gedruckt - mit transparentem PLA, (wenn ich mich richtig erinnere) 50 % Infill und konzentrischem Top/Bottom-Pattern (in Cura gesliced) ist schnell gedruckt und sieht, nachdem er mit Farbe beschmiert wurde um zu sehen wie dicht der Druck ist auch nach dem Reinigen versaut aus. Licht geht durch, sieht aber eher bescheiden aus: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Ausleuchtung bei konzentrischem Druck </gallery> Als nächstes kommt die Frage: wie die LEDs und Taster montieren? um das mechanische Design zu vereinfachen, habe ich die Idee verfolgt, möglichst Gleichteile zu verwenden. In meinen letzten Leiterkarten-Bestellungen habe ich im Waste immer 1x1 mm Kupferflächen im 1,27 mm-Raster platziert, ein Streifen damit ist etwa 9,6 mm breit (bei 1,6 mm Materialdicke) - eine gute Größe für diese Anwendung. LED auf die eine Seite, Taster auf die andere und eine Idee, für die mich die Mechaniker in der Arbeit (völlig zu Recht) vermutlich nicht mehr anschauen würden: Constraining auf zwei Bezugsebenen. Normalerweise strebt man an, dass sich die Toleranzen von einer Seite aus ausbreiten, damit man die Toleranzketten in Griff halten kann. Würde hier heißen: Die Tasten sind auf die Gehäusefront referenziert und dementsprechend müssen die Taster auch an einer Ebene montiert werden, deren Toleranz sich auf die Front bezieht. Bei mir sollen die Taster aber gegen die Bodenplatte drücken. Mit vielen Nachteilen. Da es sich aktuell allerdings um ein Einzelstück handelt: Egal. Das Platinchen mit LED vorne und Taster hinten wird einfach in eine Nut im Taster eingeschoben. Bis auf einen kleinen (reproduzierbaren) Druckfehler funktioniert das prächtig. Hier die verschiedenen Designiterationen: <gallery> anykeyx6_taste_iterationen.jpg | Iterationen der Tasten 1 bis 5.5 anykeyx6_sketchup_taste_seite.png | Finales Modell der Tasten von der Seite anykeyx6_sketchup_taster_unten.png | und von unten anykeyx6_taste_einzelteile.jpg | Einzelteile der Tasten (der Taster fehlt) anykeyx6_taste_LED.jpg | Leiterkarte in die Taste eingeschoben </gallery> Mit Infill auf 100 % und der Tasterfront auf dem Druckbett entsteht eine relativ schöne Oberfläche. Da Concentric Top/Bottom-Pattern ein Kreuz in der Diagonale erzeugt hat, bin ich auf "Lines" umgestiegen, das die Taster, gemeinsam mit dem konzentrischen Rahmen fast schon "wie gekauft" aussehen lässt. Um eine bessere Farbmischung zu erzeugen (und die Taster eine eigenwillige Streuwirkung haben), habe ich etwas Band aus meinem Beschriftungsgerät (Wenn es wichtig ist: Brother P-touch) hinter den Taster geklebt. Dadurch wird die Ausleuchtung der drei LED-Kristalle zumindest ein bisschen homogener: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Zum Vergleich nochmal das Bild von oben (konzentrischer Druck) anykeyx6_beleuchtung_diffusor.jpg | links ohne Folie, rechts mit </gallery> Insgesamt hat das Sandwich eine Höhe von 12,4 mm - 0,25 mm weniger, wenn der Taster gedrückt ist. Der Kragen ist 2,5 mm nach innen versetzt. Das, plus die Dicke der Gehäuseteile, wird die Gesamtdicke des Geräts. =Gehäuse= Mit den Maßen der Tasten geht es los, wobei die Ausschnitte für diese um 0,25 mm in alle Richtungen erweitert wurden. Das bringt zwar etwas Spiel, aber bevor der Cutter angesetzt oder nochmals gedruckt werden muss, dürfen die Tasten eher ein bisschen wackeln - zumal es bei den ersten Tastern ordentlich Elefantenfüße gab. Mit einem Überstand von 7,5 mm von der Kante der Taster zu den Gehäusewänden in drei Richtungen und etwas mehr (17,5 mm) in die vierte Richtung - irgendwo muss ja die Elektronik hin - ist das Gehäuse relativ kompakt. Im inneren befinden sich zwischen den Tastern 4 mm hohe Wände - nicht zum Ausrichten, sondern vielmehr um Streulicht zwischen den Tastern zu vermeiden. Damit sich das Gehäuse nicht durchbiegt und dadurch versehentlich mehrere Taster auf einmal betätigt werden, befinden sich in den Kreuzungspunkten der Taster Erhöhungen, die die Stabilität in Z-Richtung erhöhen. Um Material und vor allem Druckzeit zu sparen, gab es zwei abgeschnittene Druckmuster, die man dank transparentem Filament auf weißem Grund fast nicht sieht: <gallery> anykeyx6_druckmuster_deckel.jpg | Druckmuster für die Aufnahme der Tasten </gallery> Als Zugentlastung des fest installierten USB-Kabels befindet sich hinter dem U-förmigen Ausschnitt eine kleine Rampe und ein Loch, durch den ein Kabelbinder passt. Die Rampe dient lediglich dazu, dass der Kabelbinder die untere Gehäusehälfte nicht nach unten drückt. Man könnte mutmaßen, dass durch die Druckschichten bedingte Treppenstruktur die Leitung sogar ein bisschen verhakt wird. 3 Löcher, durch die M2,5-Schrauben passen, dienen zur Befestigung der Bodenplatte. Insgesamt gab es 4 Iterationen, wobei nur zwei den Weg auf den Drucker gefunden haben - und das auch nur, weil sich das erste Druckteil vom Druckbett abgelöst und dadurch unschön verzogen hat. Anscheinend sind die STL-Daten nicht ganz sauber, wodurch das Modell wohl etwas in der Luft hängt. Durch einen Microstep von -0,001 in Z-Richtung wurde das Druckergebnis besser, aber die erste Lage ist trotzdem noch etwas lückig... <gallery> anykeyx6_sketchup_deckel.png | 3D-Modell des Deckels anykeyx6_deckel_vergurkt.jpg | Der erste Versuch (vergurkt) anykeyx6_Deckel.jpg | Der bessere Druck. </gallery> Das untere Gehäuseteil sind eigentlich 7 Teile und brauchte keine Revision (aber einen kleinen Eingriff mit dem Skalpell). Die Komplexität ist auch deutlich geringer. Auffallend sind zunächst die 4 "Kamine" - die Idee dahinter ist, Muttern einzulegen und diese mit dem oberen Gehäuseteil zu verschrauben. Das ganze ist (eher unbeabsichtigt) auf Pressung designed, sowohl für die Mutter, als auch in Richtung anderes Gehäuseteil. Immerhin rutscht nichts. An den Positionen der Taster befinden sich Sacklöcher/Kerben - aus einem sehr einfachen Grund: Material und Druckzeit sparen. Die Bodenplatte soll in weiten Teilen dick genug sein, dass sie stabil ist aber auf keinen Fall ein zweites Mal gedruckt werden muss. Um die Taster in der Höhe einzupassen, werden kleine Distanznippel eingesetzt, die klein sind und dadurch sehr schnell angepasst und gedruckt werden können. Weil ich keinen Sekundenkleber mehr da hatte, sind sie lediglich einseitig auf der Bodenplatte mit doppelseitigem Klebeband befestigt. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D-Modell der Bodenplatte anykeyx6_shim.png | Das 3D-Modell eines Nippel anykeyx6_bodenplatte_benippelt.jpg | Bodenplatte mit Muttern und Nippeln </gallery> Insgesamt war der Drucker etwa 4 Stunden beschäftigt, wobei er auch nicht mit maximaler Geschwindigkeit lief. Die Materialkosten liegen (ohne Probestücke und Fehldrucke) bei etwa 50 cent wenn ich mich nicht täusche, also nicht wirklich der Rede wert. =Zusammenbau= Ursprünglich habe ich einen Atmega8 im DIP-Gehäuse vorgesehen. Da es aber doch ein bisschen eng geworden wäre, kam dann doch einer im TQFP-Gehäuse zum Einsatz. Neben dem Mikrocontroller finden auch die 9 Transistoren für die LED-Ansteuerung Platz auf der Selfmade-Punktrasterplatine: <gallery> anykeyx6_platine.jpg | Bestückte Leiterkarte. </gallery> Die LED-Tasten bekommen gehörig lange Anschlussleitungen aus Kupferlackdraht, die durchgepiepst und auf passend beschriftete Klebebandstreifen landen. Miteinander verdrillt und verlötet kommen sie dann an die FETs. Gleiches Spiel für die Massen der Taster. <gallery> anykeyx6_tastenverdrahtung.jpg | Etwas Ordnung im Chaos </gallery> Damit die Tasten beim Zusammenfügen nicht immer wieder aus ihren Löchern entwischen, kommt Klebeband von außen auf das Gehäuse. Zur Sicherheit mit Nummern beschriftet, damit mit Drehen und Spiegeln nix schief geht. Tasten eingelegt, Leitungen im Gehäuse verlegt und den Kupfer-Knäuel zusammengedrückt. Papa sagte schon immer: Salat ist gesund. Das USB-Kabel liegt fest verzurrt und sehr engem Biegeradius im Gehäuse - hält (hoffentlich). <gallery> anykeyx6_boden_und_deckel.jpg | Beide Gehäusehälften anykeyx6_deckel_verklebt.jpg | Bestückungshilfe anykeyx6_deckel_assy.jpg | Deckel mit eingelegten Komponenten </gallery> In die untere Gehäusehälfte sind die Nippel schon eingeklebt und es wird spannend: passt es? Leider sind keine Senkkopfschrauben im Haus, also bleibt es mit den verzinkten Zylinderkopf-Schrauben etwas hässlich. Oder pragmatisch. Naja, es hält - und die Tasten liegen so im Gehäuse, dass sie weder (allzu sehr) klappern noch permanent gedrückt werden. Erfolg! :) Um bei den Tasten nicht im kompletten Blindflug zu sein, ziert noch ein Label und ein paar Symbole der FontAwesome die obere Reihe. Damit sollte nun nichts mehr schief geben. =Software= ==Erster Test== Die erste Testsoftware ist in Python geschrieben und lässt einen Regenbogen durchlaufen. Der Einfachheit halber fasst sie nur eine LED gleichzeitig an: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> Sieht dann als Momentaufnahme in etwa wie folgt aus: <gallery> anykeyx6_rgb_demo.jpg | Farben, yay! </gallery> ==Der OBS-Client== Ein "echtes" Plugin für OSB Studio zu schreiben spare ich mir mangels Tiefe in C++. Stattdessen nutze ich [https://github.com/Palakis/obs-websocket obs-websocket], das eine API für C# anbietet, die extrem einfach zu bedienen ist. Für die Buttons ist eine extrem rudimentäre Klasse sehr schnell zusammengehackt. Gänzlich ohne Fehlerbehandlung. Das Auslesen der Buttons erfolgt in einem Background-Worker, der Events feuert (und beim Loslassen zusätzlich die Dauer des Drückens ermittelt), das Setzen der LED-Farben erfolgt für alle 6. Hier merkt man auch wie heiß die Nadel ist mit der gestrickt wird: Zwischen dem Schreiben der beiden "Sets" legt sich die Software für eine Millisekunde schlafen. Der Grund einst einfach die dämlich - schreibt man zu schnell, geht evtl. das erste der beiden Datenpakete in der Firmware verloren, weil die Übergabe nicht (wenn man es so nennen will) threadsafe ist. Die GUI hat lediglich einen "Connect"-Button, der nur gedrückt werden sollte, wenn OBS läuft und die Hardware verbunden ist. Die Konfiguration ist ebenfalls eher grundlegend und in AnykeyOBS.exe.config zu finden. Hier kann für jede Taste die Aktiv/Inaktiv-Farbe als Hex-Code (oder named color, ungetestet) abgelegt werden, die Funktion definiert und ein Argument für diese Funktion angegeben werden. Zum Zuordnen einer Szene packt man in die Funktion "Scene" und schreibt den zugehörigen Szenen-Namen ins Argument. Für die Aufnahme heißt die Funktion "Record" und als Argument kann "Toggle", "Start" und "Stop" definiert werden. Streaming wird noch nicht unterstützt. Aus mir nicht ganz verständlichen Gründen kann der Zustand des Streamings/Recordings nur über Events ermittelt werden, dadurch bleibt die Taste mit entsprechender Zuordnung beim Start des Programms orange. Dies ist auch die (fest hinterlegte) Farbe für Übergänge zwischen Aufnahme und keine Aufnahme. Ein weiteres Feature ist das Abbrechen einer Funktion - Grundsätzlich werden die Aktionen erst beim Loslassen des Tasters getriggert - außer man drückt diesen länger als eine Sekunde. In diesem Fall wird die Aktion abgebrochen. Insgesamt kann man die Software allerhöchstens als Proof of Concept bezeichnen. Es funktioniert, irgendwie. ===Feuerprobe=== Mittlerweile durfte ich meine Schwester sogar besuchen, um ihr die Hardware zu geben. yay! Das Einrichten fand aber trotzdem online statt. obs-websockt installiert, AnykeyOBS aufs Tablet und: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Mist. Die vermutliche Ursache ist schnell gefunden: Bei manchen USB-Geräten kann der Name nicht gelesen werden. Eine Packung try-catch auf das Problem geworfen und eine Prise <code>Console.WriteLine</code>s und das Programm bleib nach dem Klick auf "Connect" geöffnet. "Leuchten die Knöppe?" - "Oh mann, wie geil" - "Also ja?". Danach hörte ich nur noch wildes Klicken. Ich glaube, das Teil gefällt. Und so sieht es aus: [[Datei:anykeyx6_demo.mp4]] =Fazit= Wo fange ich an? Beim Guten, beim Schlechten oder bei den Sachen, für die ich mich schäme? Unterm Strich: für eine sehr hemdsärmelig zusammengestrickte Hardware sieht es (ohne dass ich mich selbst loben möchte) ganz ordentlich aus. Schlimm wird es erst, wenn man unter die Haube schaut. Das dafür aber auch konsequent. Das Gute: * Meine Schwester hat etwas, das ihr hoffentlich die Arbeit etwas erleichtert * Ich habe wieder einiges in Sachen 3D-Druck gelernt * Es hat ziemlich viel Spaß gemacht * Alles ist bunt Das Schlechte: * Decoupling, welches Decoupling? * LEDs ** Nicht sonderlich hell ** Flackern bei USB-Traffic (durch INT0) ** In dunkler Umgebung zu hell und bei Tageslicht schlecht sichtbar * Das Setzen von LEDs und Tastendrücke können verschluckt werden * Taster ** Können auch von der Gehäuseunterseite betätigt werden ** Relativ laut (im Video hörbar) ** Wackeln, sind schief und haben keine Führung * Software ** An allen Ecken und Enden rudimentär, wenn etwas ausfällt, funktioniert erst einmal nichts ** Kein automatisches Verbinden mit OBS und der Hardware ** Keine GUI für die Konfiguration ** So gut wie keine Funktionen in OBS unterstützt ** Außer OBS-Steuerung keine weiteren Funktionen * Keine Standby-States =Downloads= * SketchUp-Dateien, zugehörige STLs, Firmware und C#-Software um mit OBS zu sprechen. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] efe46a73bef9561c95d0058d3843023537ec7faf 1582 1580 2020-05-10T20:06:41Z Chris 2 Download-Link hinzugefügt wikitext text/x-wiki [[Datei:anykeyx6_komplett.jpg|thumb|Fertig aufgebaute Hardware (Farben leicht retuschiert)]] Meine Schwester ist Lehrerin. Ein Job, um den ich sie nicht beneide - gerade in 2020. Hier in Bayern fängt (Stand Anfang Mai) das Leben an der Schule langsam wieder an, parallel zum Unterricht in den Schulen müssen jedoch die daheim bleibenden Kinder noch unterrichtet werden. Wenn man die eigene Arbeit ernst nimmt, ist das kein Spaß. Klar, man könnte für das Eigenstudium einfach Arbeitsblätter über den Zaun werfen und auf Seiten in den Büchern verweisen, aber wenn ich da an meine eigene Schulzeit und die eher extrinsische Motivation denke... Obwohl meine Schwester schon sehr viel digital hat, braucht Unterricht (gerade bei Sprachen) auch jemanden, der/die vor der Klasse spricht und natürlich ist eigenständiges Lernen für viele nicht ganz einfach. Aus diesem Grund hat meine Schwester angefangen, Videos zu machen. Vorerst nur mit ausgedruckten Blättern und dem Handy auf dem Stativ. Um Ihre digitalen Materialien besser nutzen zu können, fragte sie dann doch mal nach einem screen recorder. [https://obsproject.com/ OBS] war schnell installiert und eingerichtet. Blöd nur, dass sie keinen zweiten Monitor (bzw. Displayport-Adapter) für ihr MS Surface hat. Damit ihre Schüler sie auch mal sehen können (oder auch mal "Tafelunterricht" zu machen), habe ich ihr mehrere Szenen in OBS eingerichtet: * Bildschirmaufnahme * Bildschirmaufnahme + Kamera in der Ecke * Kamera Blöd ist nur, dass sie ohne besagten zweiten Bildschirm für jede Aktion OBS in den Vordergrund holen muss. Zwar kann man dort auch globale Hotkeys anlegen, aber ohne vollständige Tastatur läuft man sehr schnell Gefahr, Doppelbelegungen zu bekommen und dadurch sehr merkwürdiges Verhalten am PC zu haben. Gleichzeitig sieht man nicht, was OBS nun tatsächlich macht. Ja, man kann eine Fernbedienung für OBS auf dem Tablet oder Smartphone installieren, aber das schafft eigentlich nur mehr Probleme als es löst, zumal man die (freien) Clients, die ich auf Anhieb gefunden hab für jede Session neu konfigurieren muss. Zudem muss das Gerät am Laufen halten und kann die Tasten nicht erfühlen. Das lenkt unnötig ab und erhöht auch die Akzeptanz nicht wirklich. Auch fertige Lösungen wie das Elgato Stream Deck ist für die (hoffentlich) kurze Nutzungsdauer unverhältnismäßig teuer. Gleichzeitig sitzt hier ein Ingenieur herum, der aufgrund der aktuellen Situation erst einmal Gleitzeit abbaut. =Die Idee= Da kann man doch was basteln. Ein paar Taster, ein paar LEDs, ein bisschen Firmware und noch ein paar Zeilen Code auf dem PC. Was soll daran so aufwändig sein? Um eines vorweg zu nehmen: Übers Ziel hinausschießen, das kann daran aufwändig werden. Ziel ist, 6-8 bunt beleuchtete Taster zu haben, die in OBS eingebunden werden können. Der Mikrocontroller ist schnell gefunden. Um nicht zu weit von den Codebeispielen von [https://www.obdev.at/products/vusb/index-de.html V-USB] zu sein, soll ein oller ATmega8 zum Einsatz kommen. Weil ich schon länger was mit intelligenten LEDs machen wollte, liegt schon viel zu lange ein Streifen mit WS2812B herum. Der Plan war, diese – womöglich sogar noch auf dem Streifen – auf Taster zu kleben. Natürlich muss der [[wpde:Woman acceptance factor|WAF]] auch halbwegs passen, deshalb ist ein nicht zu schäbiges Gehäuse angesagt. 3D-Drucker sei dank bin ich auch dazu (zumindest seitens der Ausstattung) in der Lage. =Elektronik= Die Ernüchterung kam schneller als erwartet. Dass die Ansteuerung der LEDs zeitkritisch ist, wusste ich. Dass das auch für V-USB gilt, ebenfalls. Dass man beides nicht so einfach kombinieren kann, würde dann sehr schnell klar. Der USB-Stack braucht zwingend einen Pin-Interrupt, für die Ansteuerung der LEDs muss dieser aber abgeschaltet werden – sonst blinkt alles wie ein Weihnachtsbaum auf LSD. Tim (aka cpldcpu) hat sich die Mühe gemacht, V-USB mit [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling zu ermöglichen] - gleichzeitig sogar mit entsprechender LED. Den Weg wollte ich nicht gehen, weil das potenziell an anderen Stellen schmerzhaft werden könnte. Ok, was nun? Ein Coprozessor, der UART/I²C auf das LED-Protokoll umwandelt? Eigentlich wollte ich kein Mehrprozessor-System bauen – und auch hier bleibt das Problem mit Interrupts vs. keine Interrupts, auch durch die Einschränkungen durch USI dürfte das noch etwas unentspannter sein. Da ist guter Rat teuer. Auf einfarbige LEDs wollte ich aber auch nicht zurückgehen. ==LED-Treiber== 6 RGB-LEDs mit PWM anzusteuern, braucht es 18 PWM-Kanäle. Das hat glaube ich kein AVR8. ich habe zwar noch einen PCA9685 herumliegen, der aber auch nur 16 Kanäle bereitstellt. Zudem nimmt das Teil mit seinem Breakout-Board relativ viel Platz ein. Zu viel für das, was ich vor dem inneren Auge habe. Habe ich 18 Kanäle geschrieben? Jein. Betreibt man Multiplexing, reichen zwischen 3 und 6. Schlussendlich habe ich mich dafür entschieden, die Farben in den Multiplex zu nehmen und den PWM pro Taste laufen zu lassen - mit entsprechenden Einbußen der Helligkeit (ein Drittel). Aber wo bekommt man an einem ATmega8 6 synchrone PWM-Kanäle her? Ganz einfach: gar nicht. Zumindest in Hardware - anders schaut es in Software aus, wo es auch keine richtige PWM ist, sondern eher eine Pulsleistungsmodulation (kurz PDM - einen passenden Begriff konnte ich finden, daher die Neukreation), wie sie 2011 auf der [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite] schon beschrieben wurde. Um es kurz zu beschreiben: bei gewöhnlicher PWM gibt es für jeden Kanal zwei Schaltzeitpunkte, von denen einer pro Kanal individuell ist (da er den Helligkeitswert vorgibt). Hat man n Kanäle, gibt es n Zeitpunkte, die man möglichst zielgenau treffen muss. Gerade wenn diese nah beieinander liegen, kann das zu Timingproblemen führen. Der hier verwendete Dimmer funktioniert anders. Man muss dabei bedenken, dass es beim Dimmen von LEDs relativ egal ist, ob sie über einen Zyklus am Stück an sind, oder ob sie zwischendurch ausgeschaltet werden können - wichtig ist unterm Strich nur, wie viel sie im im Laufe eines Zyklus aktiv sind. Bei einer Auflösung von b bit gibt es bei dieser Methode b Zeitpunkte - ganz egal wie viele Kanäle man verwendet und: deren Timing ist fest. Zudem sind diese sind zeitlich immer mit Faktor 2 voneinander getrennt. Nun schaltet man den Kanal immer dann an, wenn im Helligkeitswert das "Bit" des zugehörigen Zeitschlitzes aktiv ist. Da es visuell deutlich besser als mit Text funktioniert, hier mal zwei Beispiele mit einer Modulation mit 3 Bit. Die Wertigkeit steht links, die An-Zeiten entsprechen den grünen Blöcken (deren X-Achse der Zeit entspricht) und die nötigen Interrupts sind mit roten Pfeilen markiert: <gallery> anykeyx6_pwm.png | Pulsweitenmodulation anykeyx6_plm.png | Pulsleistungsmodulation </gallery> Betrachtet man die aktive Fläche der einzelnen Helligkeitswerte, kommt man auf das gleiche - nur dass die PDM deutlich ressourcenschonender ist. Dazu kommt der Effekt, dass durch das "Zerhacken" der PWM die LEDs mit einer höheren Frequenz flackern (auch wenn sie variiert). Dadurch wird der Stroboskop-Effekt verringert - des einen Freud ist des anderen Leid: achtet man auf EMV, wird es and er Stelle unangenehmer. Aber genug dazu. Aufgrund des Multiplexing gibt es, wie oben beschrieben, nur ein Drittel an Helligkeit. Die meisten LEDs halten bei pulsförmiger Ansteuerung deutlich mehr Strom als im Dauerbetrieb aus weil der limitierende Faktor die Erwärmung ist. Da die LEDs (im 5050-Gehäuse) für den Aufbau von einem LED-Streifen "geerntet" wurden, habe ich kein Datenblatt zur Komponente, aber Wissen: z. B. kommt für den roten Strang ein 330 Ohm-Widerstand zum Einsatz, bei 12 V und 3 roten LEDs in Reihe mit ca. 1,85 V Vorwärtsspannung sind das etwa 20 mA. Ohne weitere Infos zu maximalen Strömen und weil die Helligkeit eigentlich reichen sollte, bin ich bei diesem Strom geblieben. ==Taster== Die Taster kommen direkt an IOs und sind gegen Masse verschaltet. Eine rudimentäre Entprellung wird in Software gemacht. ==USB== Die USB-Beschaltung entspricht weitestgehend der aus den Beispielen von Objective Development. Aus reiner Faulheit habe ich die Schutzbeschaltung vom [[USB-Fußtaster]] übernommen. Sprichwörtlich: Die nötigen Bauteile bestückt und die Leiterkarte auf die passende Größe gestutzt. ==Schaltplan== Die gesamte Schaltung ist also relativ einfach. Als FETs für die LEDs kommen BSS84 (p-Kanal, aufseiten der Anoden) und BSS138 (n-Kanal, aufseiten der Kathoden) zum Einsatz. Aufgrund der Komplexität reicht es als Handskizze: <gallery> anykeyx6_sch.png | Schaltplan - unbekannter Künstler, 2020, digital </gallery> =Firmware= Die Firmware ist erstaunlich einfach, zumal ich mich nicht sonderlich bemüht habe. Die LEDs werden mit der oben beschriebenen Methode (in leddrv.c) angesteuert, wobei zusätzlich noch eine Fading-Funktion zum Einsatz kommt. Das entlastet den USB-Stack und verringert das Flackern (siehe weiter unten) Die Tasten werden (sofern die PWM nicht höhere Priorität hat) jede Millisekunde abgefragt (<code>buttons_tick()</code>) und wenn der Pegel low (Taste gedrückt) ist, ein Zähler inkrementiert. Bei High-Pegel wird der Zähler auf 0 zurückgesetzt. Ist der Zähler größer als 10, gilt die entsprechende Taste gedrückt. Alle Buttons in einem Byte können über die Methode <code>buttons_values()</code> abgefragt werden. In Sachen USB wird ein Out-Report (PC -> Device) mit Netto 16 Byte und ein In-Report mit Netto 8 Byte (Device -> PC) verwendet. Der Out-Report dient zum Setzen der LEDs und sieht wie folgt aus: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index der LED (1-6) * <span class="hb2">Rx</span>: Rot-Wert der LED (0 ... 255) * <span class="hb3">Gx</span>: Grün-Wert der LED (0 ... 255) * <span class="hb4">Bx</span>: Blau-Wert der LED (0 ... 255) * <span class="hb5">Tx</span>: Dauer für den Übergang (0 ... 255, in 5 ms-Schritten) Es können somit 3 Farben gleichzeitig geschrieben werden, Index 0 wird nicht verwendet, da es üblicherweise der Init-Wert für Arrays ist und somit nicht versehentlich die Farbe einer Taste gesetzt wird. Der In-Report ist denkbar einfach, im ersten Byte steht das Bit-Muster der aktuell gedrückten Taster: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> Der Report wird bei jeder Änderung des Zustands der Taster gesendet. Das ist in mehrerlei Hinsicht nicht ganz ideal, da zum einen der Initiale Zustand (nach Öffnen des Devices) nicht ermittelt werden kann und falls doch mal ein USB-Paket verloren geht, verpasst man Tastendrücke. Aber: es musste schnell gehen. =Mechanik= Die Mechanik ist (zumindest für mich als Neuling in Sachen Design und 3D-Druck) ein Stück aufwändiger. Einfach nur die Leiterkarte auf den Tisch zu knallen geht hier nicht, es muss nicht wie aus dem Ei gepellt aussehen, aber nicht nur aus der Kategorie "form follows function" sein. Um schnell voran zu kommen, kam das MS Paint im 3D-Design zum Einsatz: SketchUp. Mit allen Einschränkungen und fehlender Parametrisierung bin ich darin leider noch immer am schnellsten, etwas für den Druck vorzubereiten. ==Tasten== Mit ein bisschen Zeichnen in 2D-Software stellte sich heraus, dass rechteckige Tasten mit 15 mm Breite und Höhe, einer Abrundung mit Radius 2,5 mm und einem Abstand von 5 mm zueinander eine angenehme Haptik aufweisen. Ein erstes Muster mit Kragen (damit die Taste nicht durchs Gehäuse fällt) ist schnell gedruckt - mit transparentem PLA, (wenn ich mich richtig erinnere) 50 % Infill und konzentrischem Top/Bottom-Pattern (in Cura gesliced) ist schnell gedruckt und sieht, nachdem er mit Farbe beschmiert wurde um zu sehen wie dicht der Druck ist auch nach dem Reinigen versaut aus. Licht geht durch, sieht aber eher bescheiden aus: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Ausleuchtung bei konzentrischem Druck </gallery> Als nächstes kommt die Frage: wie die LEDs und Taster montieren? um das mechanische Design zu vereinfachen, habe ich die Idee verfolgt, möglichst Gleichteile zu verwenden. In meinen letzten Leiterkarten-Bestellungen habe ich im Waste immer 1x1 mm Kupferflächen im 1,27 mm-Raster platziert, ein Streifen damit ist etwa 9,6 mm breit (bei 1,6 mm Materialdicke) - eine gute Größe für diese Anwendung. LED auf die eine Seite, Taster auf die andere und eine Idee, für die mich die Mechaniker in der Arbeit (völlig zu Recht) vermutlich nicht mehr anschauen würden: Constraining auf zwei Bezugsebenen. Normalerweise strebt man an, dass sich die Toleranzen von einer Seite aus ausbreiten, damit man die Toleranzketten in Griff halten kann. Würde hier heißen: Die Tasten sind auf die Gehäusefront referenziert und dementsprechend müssen die Taster auch an einer Ebene montiert werden, deren Toleranz sich auf die Front bezieht. Bei mir sollen die Taster aber gegen die Bodenplatte drücken. Mit vielen Nachteilen. Da es sich aktuell allerdings um ein Einzelstück handelt: Egal. Das Platinchen mit LED vorne und Taster hinten wird einfach in eine Nut im Taster eingeschoben. Bis auf einen kleinen (reproduzierbaren) Druckfehler funktioniert das prächtig. Hier die verschiedenen Designiterationen: <gallery> anykeyx6_taste_iterationen.jpg | Iterationen der Tasten 1 bis 5.5 anykeyx6_sketchup_taste_seite.png | Finales Modell der Tasten von der Seite anykeyx6_sketchup_taster_unten.png | und von unten anykeyx6_taste_einzelteile.jpg | Einzelteile der Tasten (der Taster fehlt) anykeyx6_taste_LED.jpg | Leiterkarte in die Taste eingeschoben </gallery> Mit Infill auf 100 % und der Tasterfront auf dem Druckbett entsteht eine relativ schöne Oberfläche. Da Concentric Top/Bottom-Pattern ein Kreuz in der Diagonale erzeugt hat, bin ich auf "Lines" umgestiegen, das die Taster, gemeinsam mit dem konzentrischen Rahmen fast schon "wie gekauft" aussehen lässt. Um eine bessere Farbmischung zu erzeugen (und die Taster eine eigenwillige Streuwirkung haben), habe ich etwas Band aus meinem Beschriftungsgerät (Wenn es wichtig ist: Brother P-touch) hinter den Taster geklebt. Dadurch wird die Ausleuchtung der drei LED-Kristalle zumindest ein bisschen homogener: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Zum Vergleich nochmal das Bild von oben (konzentrischer Druck) anykeyx6_beleuchtung_diffusor.jpg | links ohne Folie, rechts mit </gallery> Insgesamt hat das Sandwich eine Höhe von 12,4 mm - 0,25 mm weniger, wenn der Taster gedrückt ist. Der Kragen ist 2,5 mm nach innen versetzt. Das, plus die Dicke der Gehäuseteile, wird die Gesamtdicke des Geräts. =Gehäuse= Mit den Maßen der Tasten geht es los, wobei die Ausschnitte für diese um 0,25 mm in alle Richtungen erweitert wurden. Das bringt zwar etwas Spiel, aber bevor der Cutter angesetzt oder nochmals gedruckt werden muss, dürfen die Tasten eher ein bisschen wackeln - zumal es bei den ersten Tastern ordentlich Elefantenfüße gab. Mit einem Überstand von 7,5 mm von der Kante der Taster zu den Gehäusewänden in drei Richtungen und etwas mehr (17,5 mm) in die vierte Richtung - irgendwo muss ja die Elektronik hin - ist das Gehäuse relativ kompakt. Im inneren befinden sich zwischen den Tastern 4 mm hohe Wände - nicht zum Ausrichten, sondern vielmehr um Streulicht zwischen den Tastern zu vermeiden. Damit sich das Gehäuse nicht durchbiegt und dadurch versehentlich mehrere Taster auf einmal betätigt werden, befinden sich in den Kreuzungspunkten der Taster Erhöhungen, die die Stabilität in Z-Richtung erhöhen. Um Material und vor allem Druckzeit zu sparen, gab es zwei abgeschnittene Druckmuster, die man dank transparentem Filament auf weißem Grund fast nicht sieht: <gallery> anykeyx6_druckmuster_deckel.jpg | Druckmuster für die Aufnahme der Tasten </gallery> Als Zugentlastung des fest installierten USB-Kabels befindet sich hinter dem U-förmigen Ausschnitt eine kleine Rampe und ein Loch, durch den ein Kabelbinder passt. Die Rampe dient lediglich dazu, dass der Kabelbinder die untere Gehäusehälfte nicht nach unten drückt. Man könnte mutmaßen, dass durch die Druckschichten bedingte Treppenstruktur die Leitung sogar ein bisschen verhakt wird. 3 Löcher, durch die M2,5-Schrauben passen, dienen zur Befestigung der Bodenplatte. Insgesamt gab es 4 Iterationen, wobei nur zwei den Weg auf den Drucker gefunden haben - und das auch nur, weil sich das erste Druckteil vom Druckbett abgelöst und dadurch unschön verzogen hat. Anscheinend sind die STL-Daten nicht ganz sauber, wodurch das Modell wohl etwas in der Luft hängt. Durch einen Microstep von -0,001 in Z-Richtung wurde das Druckergebnis besser, aber die erste Lage ist trotzdem noch etwas lückig... <gallery> anykeyx6_sketchup_deckel.png | 3D-Modell des Deckels anykeyx6_deckel_vergurkt.jpg | Der erste Versuch (vergurkt) anykeyx6_Deckel.jpg | Der bessere Druck. </gallery> Das untere Gehäuseteil sind eigentlich 7 Teile und brauchte keine Revision (aber einen kleinen Eingriff mit dem Skalpell). Die Komplexität ist auch deutlich geringer. Auffallend sind zunächst die 4 "Kamine" - die Idee dahinter ist, Muttern einzulegen und diese mit dem oberen Gehäuseteil zu verschrauben. Das ganze ist (eher unbeabsichtigt) auf Pressung designed, sowohl für die Mutter, als auch in Richtung anderes Gehäuseteil. Immerhin rutscht nichts. An den Positionen der Taster befinden sich Sacklöcher/Kerben - aus einem sehr einfachen Grund: Material und Druckzeit sparen. Die Bodenplatte soll in weiten Teilen dick genug sein, dass sie stabil ist aber auf keinen Fall ein zweites Mal gedruckt werden muss. Um die Taster in der Höhe einzupassen, werden kleine Distanznippel eingesetzt, die klein sind und dadurch sehr schnell angepasst und gedruckt werden können. Weil ich keinen Sekundenkleber mehr da hatte, sind sie lediglich einseitig auf der Bodenplatte mit doppelseitigem Klebeband befestigt. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D-Modell der Bodenplatte anykeyx6_shim.png | Das 3D-Modell eines Nippel anykeyx6_bodenplatte_benippelt.jpg | Bodenplatte mit Muttern und Nippeln </gallery> Insgesamt war der Drucker etwa 4 Stunden beschäftigt, wobei er auch nicht mit maximaler Geschwindigkeit lief. Die Materialkosten liegen (ohne Probestücke und Fehldrucke) bei etwa 50 cent wenn ich mich nicht täusche, also nicht wirklich der Rede wert. =Zusammenbau= Ursprünglich habe ich einen Atmega8 im DIP-Gehäuse vorgesehen. Da es aber doch ein bisschen eng geworden wäre, kam dann doch einer im TQFP-Gehäuse zum Einsatz. Neben dem Mikrocontroller finden auch die 9 Transistoren für die LED-Ansteuerung Platz auf der Selfmade-Punktrasterplatine: <gallery> anykeyx6_platine.jpg | Bestückte Leiterkarte. </gallery> Die LED-Tasten bekommen gehörig lange Anschlussleitungen aus Kupferlackdraht, die durchgepiepst und auf passend beschriftete Klebebandstreifen landen. Miteinander verdrillt und verlötet kommen sie dann an die FETs. Gleiches Spiel für die Massen der Taster. <gallery> anykeyx6_tastenverdrahtung.jpg | Etwas Ordnung im Chaos </gallery> Damit die Tasten beim Zusammenfügen nicht immer wieder aus ihren Löchern entwischen, kommt Klebeband von außen auf das Gehäuse. Zur Sicherheit mit Nummern beschriftet, damit mit Drehen und Spiegeln nix schief geht. Tasten eingelegt, Leitungen im Gehäuse verlegt und den Kupfer-Knäuel zusammengedrückt. Papa sagte schon immer: Salat ist gesund. Das USB-Kabel liegt fest verzurrt und sehr engem Biegeradius im Gehäuse - hält (hoffentlich). <gallery> anykeyx6_boden_und_deckel.jpg | Beide Gehäusehälften anykeyx6_deckel_verklebt.jpg | Bestückungshilfe anykeyx6_deckel_assy.jpg | Deckel mit eingelegten Komponenten </gallery> In die untere Gehäusehälfte sind die Nippel schon eingeklebt und es wird spannend: passt es? Leider sind keine Senkkopfschrauben im Haus, also bleibt es mit den verzinkten Zylinderkopf-Schrauben etwas hässlich. Oder pragmatisch. Naja, es hält - und die Tasten liegen so im Gehäuse, dass sie weder (allzu sehr) klappern noch permanent gedrückt werden. Erfolg! :) Um bei den Tasten nicht im kompletten Blindflug zu sein, ziert noch ein Label und ein paar Symbole der FontAwesome die obere Reihe. Damit sollte nun nichts mehr schief geben. =Software= ==Erster Test== Die erste Testsoftware ist in Python geschrieben und lässt einen Regenbogen durchlaufen. Der Einfachheit halber fasst sie nur eine LED gleichzeitig an: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> Sieht dann als Momentaufnahme in etwa wie folgt aus: <gallery> anykeyx6_rgb_demo.jpg | Farben, yay! </gallery> ==Der OBS-Client== Ein "echtes" Plugin für OSB Studio zu schreiben spare ich mir mangels Tiefe in C++. Stattdessen nutze ich [https://github.com/Palakis/obs-websocket obs-websocket], das eine API für C# anbietet, die extrem einfach zu bedienen ist. Für die Buttons ist eine extrem rudimentäre Klasse sehr schnell zusammengehackt. Gänzlich ohne Fehlerbehandlung. Das Auslesen der Buttons erfolgt in einem Background-Worker, der Events feuert (und beim Loslassen zusätzlich die Dauer des Drückens ermittelt), das Setzen der LED-Farben erfolgt für alle 6. Hier merkt man auch wie heiß die Nadel ist mit der gestrickt wird: Zwischen dem Schreiben der beiden "Sets" legt sich die Software für eine Millisekunde schlafen. Der Grund einst einfach die dämlich - schreibt man zu schnell, geht evtl. das erste der beiden Datenpakete in der Firmware verloren, weil die Übergabe nicht (wenn man es so nennen will) threadsafe ist. Die GUI hat lediglich einen "Connect"-Button, der nur gedrückt werden sollte, wenn OBS läuft und die Hardware verbunden ist. Die Konfiguration ist ebenfalls eher grundlegend und in AnykeyOBS.exe.config zu finden. Hier kann für jede Taste die Aktiv/Inaktiv-Farbe als Hex-Code (oder named color, ungetestet) abgelegt werden, die Funktion definiert und ein Argument für diese Funktion angegeben werden. Zum Zuordnen einer Szene packt man in die Funktion "Scene" und schreibt den zugehörigen Szenen-Namen ins Argument. Für die Aufnahme heißt die Funktion "Record" und als Argument kann "Toggle", "Start" und "Stop" definiert werden. Streaming wird noch nicht unterstützt. Aus mir nicht ganz verständlichen Gründen kann der Zustand des Streamings/Recordings nur über Events ermittelt werden, dadurch bleibt die Taste mit entsprechender Zuordnung beim Start des Programms orange. Dies ist auch die (fest hinterlegte) Farbe für Übergänge zwischen Aufnahme und keine Aufnahme. Ein weiteres Feature ist das Abbrechen einer Funktion - Grundsätzlich werden die Aktionen erst beim Loslassen des Tasters getriggert - außer man drückt diesen länger als eine Sekunde. In diesem Fall wird die Aktion abgebrochen. Insgesamt kann man die Software allerhöchstens als Proof of Concept bezeichnen. Es funktioniert, irgendwie. ===Feuerprobe=== Mittlerweile durfte ich meine Schwester sogar besuchen, um ihr die Hardware zu geben. yay! Das Einrichten fand aber trotzdem online statt. obs-websockt installiert, AnykeyOBS aufs Tablet und: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Mist. Die vermutliche Ursache ist schnell gefunden: Bei manchen USB-Geräten kann der Name nicht gelesen werden. Eine Packung try-catch auf das Problem geworfen und eine Prise <code>Console.WriteLine</code>s und das Programm bleib nach dem Klick auf "Connect" geöffnet. "Leuchten die Knöppe?" - "Oh mann, wie geil" - "Also ja?". Danach hörte ich nur noch wildes Klicken. Ich glaube, das Teil gefällt. Und so sieht es aus: [[Datei:anykeyx6_demo.mp4]] =Fazit= Wo fange ich an? Beim Guten, beim Schlechten oder bei den Sachen, für die ich mich schäme? Unterm Strich: für eine sehr hemdsärmelig zusammengestrickte Hardware sieht es (ohne dass ich mich selbst loben möchte) ganz ordentlich aus. Schlimm wird es erst, wenn man unter die Haube schaut. Das dafür aber auch konsequent. Das Gute: * Meine Schwester hat etwas, das ihr hoffentlich die Arbeit etwas erleichtert * Ich habe wieder einiges in Sachen 3D-Druck gelernt * Es hat ziemlich viel Spaß gemacht * Alles ist bunt Das Schlechte: * Decoupling, welches Decoupling? * LEDs ** Nicht sonderlich hell ** Flackern bei USB-Traffic (durch INT0) ** In dunkler Umgebung zu hell und bei Tageslicht schlecht sichtbar * Das Setzen von LEDs und Tastendrücke können verschluckt werden * Taster ** Können auch von der Gehäuseunterseite betätigt werden ** Relativ laut (im Video hörbar) ** Wackeln, sind schief und haben keine Führung * Software ** An allen Ecken und Enden rudimentär, wenn etwas ausfällt, funktioniert erst einmal nichts ** Kein automatisches Verbinden mit OBS und der Hardware ** Keine GUI für die Konfiguration ** So gut wie keine Funktionen in OBS unterstützt ** Außer OBS-Steuerung keine weiteren Funktionen * Keine Standby-States =Downloads= * [[Datei:Anykeyx6.zip]] SketchUp-Dateien, zugehörige STLs, Firmware und C#-Software um mit OBS zu sprechen. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] 366e2ca0754ac1d34381f332504528bde4e8abaf 1584 1582 2020-05-10T20:33:30Z Chris 2 komische Formulierung korrigiert wikitext text/x-wiki [[Datei:anykeyx6_komplett.jpg|thumb|Fertig aufgebaute Hardware (Farben leicht retuschiert)]] Meine Schwester ist Lehrerin. Ein Job, um den ich sie nicht beneide - gerade in 2020. Hier in Bayern fängt (Stand Anfang Mai) das Leben an der Schule langsam wieder an, parallel zum Unterricht in den Schulen müssen jedoch die daheim bleibenden Kinder noch unterrichtet werden. Wenn man die eigene Arbeit ernst nimmt, ist das kein Spaß. Klar, man könnte für das Eigenstudium einfach Arbeitsblätter über den Zaun werfen und auf Seiten in den Büchern verweisen, aber wenn ich da an meine eigene Schulzeit und die eher extrinsische Motivation denke... Obwohl meine Schwester schon sehr viel digital hat, braucht Unterricht (gerade bei Sprachen) auch jemanden, der/die vor der Klasse spricht und natürlich ist eigenständiges Lernen für viele nicht ganz einfach. Aus diesem Grund hat meine Schwester angefangen, Videos zu machen. Vorerst nur mit ausgedruckten Blättern und dem Handy auf dem Stativ. Um Ihre digitalen Materialien besser nutzen zu können, fragte sie dann doch mal nach einem screen recorder. [https://obsproject.com/ OBS] war schnell installiert und eingerichtet. Blöd nur, dass sie keinen zweiten Monitor (bzw. Displayport-Adapter) für ihr MS Surface hat. Damit ihre Schüler sie auch mal sehen können (oder auch mal "Tafelunterricht" zu machen), habe ich ihr mehrere Szenen in OBS eingerichtet: * Bildschirmaufnahme * Bildschirmaufnahme + Kamera in der Ecke * Kamera Blöd ist nur, dass sie ohne besagten zweiten Bildschirm für jede Aktion OBS in den Vordergrund holen muss. Zwar kann man dort auch globale Hotkeys anlegen, aber ohne vollständige Tastatur läuft man sehr schnell Gefahr, Doppelbelegungen zu bekommen und dadurch sehr merkwürdiges Verhalten am PC zu haben. Gleichzeitig sieht man nicht, was OBS nun tatsächlich macht. Ja, man kann eine Fernbedienung für OBS auf dem Tablet oder Smartphone installieren, aber das schafft eigentlich nur mehr Probleme als es löst, zumal man die (freien) Clients, die ich auf Anhieb gefunden hab für jede Session neu konfigurieren muss. Zudem muss das Gerät am Laufen halten und kann die Tasten nicht erfühlen. Das lenkt unnötig ab und erhöht auch die Akzeptanz nicht wirklich. Auch fertige Lösungen wie das Elgato Stream Deck ist für die (hoffentlich) kurze Nutzungsdauer unverhältnismäßig teuer. Gleichzeitig sitzt hier ein Ingenieur herum, der aufgrund der aktuellen Situation erst einmal Gleitzeit abbaut. =Die Idee= Da kann man doch was basteln. Ein paar Taster, ein paar LEDs, ein bisschen Firmware und noch ein paar Zeilen Code auf dem PC. Was soll daran so aufwändig sein? Um eines vorweg zu nehmen: Übers Ziel hinausschießen, das kann daran aufwändig werden. Ziel ist, 6-8 bunt beleuchtete Taster zu haben, die in OBS eingebunden werden können. Der Mikrocontroller ist schnell gefunden. Um nicht zu weit von den Codebeispielen von [https://www.obdev.at/products/vusb/index-de.html V-USB] zu sein, soll ein oller ATmega8 zum Einsatz kommen. Weil ich schon länger was mit intelligenten LEDs machen wollte, liegt schon viel zu lange ein Streifen mit WS2812B herum. Der Plan war, diese – womöglich sogar noch auf dem Streifen – auf Taster zu kleben. Natürlich muss der [[wpde:Woman acceptance factor|WAF]] auch halbwegs passen, deshalb ist ein nicht zu schäbiges Gehäuse angesagt. 3D-Drucker sei dank bin ich auch dazu (zumindest seitens der Ausstattung) in der Lage. =Elektronik= Die Ernüchterung kam schneller als erwartet. Dass die Ansteuerung der LEDs zeitkritisch ist, wusste ich. Dass das auch für V-USB gilt, ebenfalls. Dass man beides nicht so einfach kombinieren kann, würde dann sehr schnell klar. Der USB-Stack braucht zwingend einen Pin-Interrupt, für die Ansteuerung der LEDs muss dieser aber abgeschaltet werden – sonst blinkt alles wie ein Weihnachtsbaum auf LSD. Tim (aka cpldcpu) hat sich die Mühe gemacht, V-USB mit [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling zu ermöglichen] - gleichzeitig sogar mit entsprechender LED. Den Weg wollte ich nicht gehen, weil das potenziell an anderen Stellen schmerzhaft werden könnte. Ok, was nun? Ein Coprozessor, der UART/I²C auf das LED-Protokoll umwandelt? Eigentlich wollte ich kein Mehrprozessor-System bauen – und auch hier bleibt das Problem mit Interrupts vs. keine Interrupts, auch durch die Einschränkungen durch USI dürfte das noch etwas unentspannter sein. Da ist guter Rat teuer. Auf einfarbige LEDs wollte ich aber auch nicht zurückgehen. ==LED-Treiber== 6 RGB-LEDs mit PWM anzusteuern, braucht es 18 PWM-Kanäle. Das hat glaube ich kein AVR8. ich habe zwar noch einen PCA9685 herumliegen, der aber auch nur 16 Kanäle bereitstellt. Zudem nimmt das Teil mit seinem Breakout-Board relativ viel Platz ein. Zu viel für das, was ich vor dem inneren Auge habe. Habe ich 18 Kanäle geschrieben? Jein. Betreibt man Multiplexing, reichen zwischen 3 und 6. Schlussendlich habe ich mich dafür entschieden, die Farben in den Multiplex zu nehmen und den PWM pro Taste laufen zu lassen - mit entsprechenden Einbußen der Helligkeit (ein Drittel). Aber wo bekommt man an einem ATmega8 6 synchrone PWM-Kanäle her? Ganz einfach: gar nicht. Zumindest in Hardware - anders schaut es in Software aus, wo es auch keine richtige PWM ist, sondern eher eine Pulsleistungsmodulation (kurz PDM - einen passenden Begriff konnte ich finden, daher die Neukreation), wie sie 2011 auf der [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite] schon beschrieben wurde. Um es kurz zu beschreiben: bei gewöhnlicher PWM gibt es für jeden Kanal zwei Schaltzeitpunkte, von denen einer pro Kanal individuell ist (da er den Helligkeitswert vorgibt). Hat man n Kanäle, gibt es n Zeitpunkte, die man möglichst zielgenau treffen muss. Gerade wenn diese nah beieinander liegen, kann das zu Timingproblemen führen. Der hier verwendete Dimmer funktioniert anders. Man muss dabei bedenken, dass es beim Dimmen von LEDs relativ egal ist, ob sie über einen Zyklus am Stück an sind, oder ob sie zwischendurch ausgeschaltet werden - wichtig ist unterm Strich nur, wie viel sie im im Laufe eines Zyklus aktiv sind. Bei einer Auflösung von b bit gibt es bei dieser Methode b Zeitpunkte - ganz egal wie viele Kanäle man verwendet und: deren Timing ist fest. Zudem sind diese sind zeitlich immer mit Faktor 2 voneinander getrennt. Nun schaltet man den Kanal immer dann an, wenn im Helligkeitswert das "Bit" des zugehörigen Zeitschlitzes aktiv ist. Da es visuell deutlich besser als mit Text funktioniert, hier mal zwei Beispiele mit einer Modulation mit 3 Bit. Die Wertigkeit steht links, die An-Zeiten entsprechen den grünen Blöcken (deren X-Achse der Zeit entspricht) und die nötigen Interrupts sind mit roten Pfeilen markiert: <gallery> anykeyx6_pwm.png | Pulsweitenmodulation anykeyx6_plm.png | Pulsleistungsmodulation </gallery> Betrachtet man die aktive Fläche der einzelnen Helligkeitswerte, kommt man auf das gleiche - nur dass die PDM deutlich ressourcenschonender ist. Dazu kommt der Effekt, dass durch das "Zerhacken" der PWM die LEDs mit einer höheren Frequenz flackern (auch wenn sie variiert). Dadurch wird der Stroboskop-Effekt verringert - des einen Freud ist des anderen Leid: achtet man auf EMV, wird es and er Stelle unangenehmer. Aber genug dazu. Aufgrund des Multiplexing gibt es, wie oben beschrieben, nur ein Drittel an Helligkeit. Die meisten LEDs halten bei pulsförmiger Ansteuerung deutlich mehr Strom als im Dauerbetrieb aus weil der limitierende Faktor die Erwärmung ist. Da die LEDs (im 5050-Gehäuse) für den Aufbau von einem LED-Streifen "geerntet" wurden, habe ich kein Datenblatt zur Komponente, aber Wissen: z. B. kommt für den roten Strang ein 330 Ohm-Widerstand zum Einsatz, bei 12 V und 3 roten LEDs in Reihe mit ca. 1,85 V Vorwärtsspannung sind das etwa 20 mA. Ohne weitere Infos zu maximalen Strömen und weil die Helligkeit eigentlich reichen sollte, bin ich bei diesem Strom geblieben. ==Taster== Die Taster kommen direkt an IOs und sind gegen Masse verschaltet. Eine rudimentäre Entprellung wird in Software gemacht. ==USB== Die USB-Beschaltung entspricht weitestgehend der aus den Beispielen von Objective Development. Aus reiner Faulheit habe ich die Schutzbeschaltung vom [[USB-Fußtaster]] übernommen. Sprichwörtlich: Die nötigen Bauteile bestückt und die Leiterkarte auf die passende Größe gestutzt. ==Schaltplan== Die gesamte Schaltung ist also relativ einfach. Als FETs für die LEDs kommen BSS84 (p-Kanal, aufseiten der Anoden) und BSS138 (n-Kanal, aufseiten der Kathoden) zum Einsatz. Aufgrund der Komplexität reicht es als Handskizze: <gallery> anykeyx6_sch.png | Schaltplan - unbekannter Künstler, 2020, digital </gallery> =Firmware= Die Firmware ist erstaunlich einfach, zumal ich mich nicht sonderlich bemüht habe. Die LEDs werden mit der oben beschriebenen Methode (in leddrv.c) angesteuert, wobei zusätzlich noch eine Fading-Funktion zum Einsatz kommt. Das entlastet den USB-Stack und verringert das Flackern (siehe weiter unten) Die Tasten werden (sofern die PWM nicht höhere Priorität hat) jede Millisekunde abgefragt (<code>buttons_tick()</code>) und wenn der Pegel low (Taste gedrückt) ist, ein Zähler inkrementiert. Bei High-Pegel wird der Zähler auf 0 zurückgesetzt. Ist der Zähler größer als 10, gilt die entsprechende Taste gedrückt. Alle Buttons in einem Byte können über die Methode <code>buttons_values()</code> abgefragt werden. In Sachen USB wird ein Out-Report (PC -> Device) mit Netto 16 Byte und ein In-Report mit Netto 8 Byte (Device -> PC) verwendet. Der Out-Report dient zum Setzen der LEDs und sieht wie folgt aus: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index der LED (1-6) * <span class="hb2">Rx</span>: Rot-Wert der LED (0 ... 255) * <span class="hb3">Gx</span>: Grün-Wert der LED (0 ... 255) * <span class="hb4">Bx</span>: Blau-Wert der LED (0 ... 255) * <span class="hb5">Tx</span>: Dauer für den Übergang (0 ... 255, in 5 ms-Schritten) Es können somit 3 Farben gleichzeitig geschrieben werden, Index 0 wird nicht verwendet, da es üblicherweise der Init-Wert für Arrays ist und somit nicht versehentlich die Farbe einer Taste gesetzt wird. Der In-Report ist denkbar einfach, im ersten Byte steht das Bit-Muster der aktuell gedrückten Taster: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> Der Report wird bei jeder Änderung des Zustands der Taster gesendet. Das ist in mehrerlei Hinsicht nicht ganz ideal, da zum einen der Initiale Zustand (nach Öffnen des Devices) nicht ermittelt werden kann und falls doch mal ein USB-Paket verloren geht, verpasst man Tastendrücke. Aber: es musste schnell gehen. =Mechanik= Die Mechanik ist (zumindest für mich als Neuling in Sachen Design und 3D-Druck) ein Stück aufwändiger. Einfach nur die Leiterkarte auf den Tisch zu knallen geht hier nicht, es muss nicht wie aus dem Ei gepellt aussehen, aber nicht nur aus der Kategorie "form follows function" sein. Um schnell voran zu kommen, kam das MS Paint im 3D-Design zum Einsatz: SketchUp. Mit allen Einschränkungen und fehlender Parametrisierung bin ich darin leider noch immer am schnellsten, etwas für den Druck vorzubereiten. ==Tasten== Mit ein bisschen Zeichnen in 2D-Software stellte sich heraus, dass rechteckige Tasten mit 15 mm Breite und Höhe, einer Abrundung mit Radius 2,5 mm und einem Abstand von 5 mm zueinander eine angenehme Haptik aufweisen. Ein erstes Muster mit Kragen (damit die Taste nicht durchs Gehäuse fällt) ist schnell gedruckt - mit transparentem PLA, (wenn ich mich richtig erinnere) 50 % Infill und konzentrischem Top/Bottom-Pattern (in Cura gesliced) ist schnell gedruckt und sieht, nachdem er mit Farbe beschmiert wurde um zu sehen wie dicht der Druck ist auch nach dem Reinigen versaut aus. Licht geht durch, sieht aber eher bescheiden aus: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Ausleuchtung bei konzentrischem Druck </gallery> Als nächstes kommt die Frage: wie die LEDs und Taster montieren? um das mechanische Design zu vereinfachen, habe ich die Idee verfolgt, möglichst Gleichteile zu verwenden. In meinen letzten Leiterkarten-Bestellungen habe ich im Waste immer 1x1 mm Kupferflächen im 1,27 mm-Raster platziert, ein Streifen damit ist etwa 9,6 mm breit (bei 1,6 mm Materialdicke) - eine gute Größe für diese Anwendung. LED auf die eine Seite, Taster auf die andere und eine Idee, für die mich die Mechaniker in der Arbeit (völlig zu Recht) vermutlich nicht mehr anschauen würden: Constraining auf zwei Bezugsebenen. Normalerweise strebt man an, dass sich die Toleranzen von einer Seite aus ausbreiten, damit man die Toleranzketten in Griff halten kann. Würde hier heißen: Die Tasten sind auf die Gehäusefront referenziert und dementsprechend müssen die Taster auch an einer Ebene montiert werden, deren Toleranz sich auf die Front bezieht. Bei mir sollen die Taster aber gegen die Bodenplatte drücken. Mit vielen Nachteilen. Da es sich aktuell allerdings um ein Einzelstück handelt: Egal. Das Platinchen mit LED vorne und Taster hinten wird einfach in eine Nut im Taster eingeschoben. Bis auf einen kleinen (reproduzierbaren) Druckfehler funktioniert das prächtig. Hier die verschiedenen Designiterationen: <gallery> anykeyx6_taste_iterationen.jpg | Iterationen der Tasten 1 bis 5.5 anykeyx6_sketchup_taste_seite.png | Finales Modell der Tasten von der Seite anykeyx6_sketchup_taster_unten.png | und von unten anykeyx6_taste_einzelteile.jpg | Einzelteile der Tasten (der Taster fehlt) anykeyx6_taste_LED.jpg | Leiterkarte in die Taste eingeschoben </gallery> Mit Infill auf 100 % und der Tasterfront auf dem Druckbett entsteht eine relativ schöne Oberfläche. Da Concentric Top/Bottom-Pattern ein Kreuz in der Diagonale erzeugt hat, bin ich auf "Lines" umgestiegen, das die Taster, gemeinsam mit dem konzentrischen Rahmen fast schon "wie gekauft" aussehen lässt. Um eine bessere Farbmischung zu erzeugen (und die Taster eine eigenwillige Streuwirkung haben), habe ich etwas Band aus meinem Beschriftungsgerät (Wenn es wichtig ist: Brother P-touch) hinter den Taster geklebt. Dadurch wird die Ausleuchtung der drei LED-Kristalle zumindest ein bisschen homogener: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Zum Vergleich nochmal das Bild von oben (konzentrischer Druck) anykeyx6_beleuchtung_diffusor.jpg | links ohne Folie, rechts mit </gallery> Insgesamt hat das Sandwich eine Höhe von 12,4 mm - 0,25 mm weniger, wenn der Taster gedrückt ist. Der Kragen ist 2,5 mm nach innen versetzt. Das, plus die Dicke der Gehäuseteile, wird die Gesamtdicke des Geräts. =Gehäuse= Mit den Maßen der Tasten geht es los, wobei die Ausschnitte für diese um 0,25 mm in alle Richtungen erweitert wurden. Das bringt zwar etwas Spiel, aber bevor der Cutter angesetzt oder nochmals gedruckt werden muss, dürfen die Tasten eher ein bisschen wackeln - zumal es bei den ersten Tastern ordentlich Elefantenfüße gab. Mit einem Überstand von 7,5 mm von der Kante der Taster zu den Gehäusewänden in drei Richtungen und etwas mehr (17,5 mm) in die vierte Richtung - irgendwo muss ja die Elektronik hin - ist das Gehäuse relativ kompakt. Im inneren befinden sich zwischen den Tastern 4 mm hohe Wände - nicht zum Ausrichten, sondern vielmehr um Streulicht zwischen den Tastern zu vermeiden. Damit sich das Gehäuse nicht durchbiegt und dadurch versehentlich mehrere Taster auf einmal betätigt werden, befinden sich in den Kreuzungspunkten der Taster Erhöhungen, die die Stabilität in Z-Richtung erhöhen. Um Material und vor allem Druckzeit zu sparen, gab es zwei abgeschnittene Druckmuster, die man dank transparentem Filament auf weißem Grund fast nicht sieht: <gallery> anykeyx6_druckmuster_deckel.jpg | Druckmuster für die Aufnahme der Tasten </gallery> Als Zugentlastung des fest installierten USB-Kabels befindet sich hinter dem U-förmigen Ausschnitt eine kleine Rampe und ein Loch, durch den ein Kabelbinder passt. Die Rampe dient lediglich dazu, dass der Kabelbinder die untere Gehäusehälfte nicht nach unten drückt. Man könnte mutmaßen, dass durch die Druckschichten bedingte Treppenstruktur die Leitung sogar ein bisschen verhakt wird. 3 Löcher, durch die M2,5-Schrauben passen, dienen zur Befestigung der Bodenplatte. Insgesamt gab es 4 Iterationen, wobei nur zwei den Weg auf den Drucker gefunden haben - und das auch nur, weil sich das erste Druckteil vom Druckbett abgelöst und dadurch unschön verzogen hat. Anscheinend sind die STL-Daten nicht ganz sauber, wodurch das Modell wohl etwas in der Luft hängt. Durch einen Microstep von -0,001 in Z-Richtung wurde das Druckergebnis besser, aber die erste Lage ist trotzdem noch etwas lückig... <gallery> anykeyx6_sketchup_deckel.png | 3D-Modell des Deckels anykeyx6_deckel_vergurkt.jpg | Der erste Versuch (vergurkt) anykeyx6_Deckel.jpg | Der bessere Druck. </gallery> Das untere Gehäuseteil sind eigentlich 7 Teile und brauchte keine Revision (aber einen kleinen Eingriff mit dem Skalpell). Die Komplexität ist auch deutlich geringer. Auffallend sind zunächst die 4 "Kamine" - die Idee dahinter ist, Muttern einzulegen und diese mit dem oberen Gehäuseteil zu verschrauben. Das ganze ist (eher unbeabsichtigt) auf Pressung designed, sowohl für die Mutter, als auch in Richtung anderes Gehäuseteil. Immerhin rutscht nichts. An den Positionen der Taster befinden sich Sacklöcher/Kerben - aus einem sehr einfachen Grund: Material und Druckzeit sparen. Die Bodenplatte soll in weiten Teilen dick genug sein, dass sie stabil ist aber auf keinen Fall ein zweites Mal gedruckt werden muss. Um die Taster in der Höhe einzupassen, werden kleine Distanznippel eingesetzt, die klein sind und dadurch sehr schnell angepasst und gedruckt werden können. Weil ich keinen Sekundenkleber mehr da hatte, sind sie lediglich einseitig auf der Bodenplatte mit doppelseitigem Klebeband befestigt. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D-Modell der Bodenplatte anykeyx6_shim.png | Das 3D-Modell eines Nippel anykeyx6_bodenplatte_benippelt.jpg | Bodenplatte mit Muttern und Nippeln </gallery> Insgesamt war der Drucker etwa 4 Stunden beschäftigt, wobei er auch nicht mit maximaler Geschwindigkeit lief. Die Materialkosten liegen (ohne Probestücke und Fehldrucke) bei etwa 50 cent wenn ich mich nicht täusche, also nicht wirklich der Rede wert. =Zusammenbau= Ursprünglich habe ich einen Atmega8 im DIP-Gehäuse vorgesehen. Da es aber doch ein bisschen eng geworden wäre, kam dann doch einer im TQFP-Gehäuse zum Einsatz. Neben dem Mikrocontroller finden auch die 9 Transistoren für die LED-Ansteuerung Platz auf der Selfmade-Punktrasterplatine: <gallery> anykeyx6_platine.jpg | Bestückte Leiterkarte. </gallery> Die LED-Tasten bekommen gehörig lange Anschlussleitungen aus Kupferlackdraht, die durchgepiepst und auf passend beschriftete Klebebandstreifen landen. Miteinander verdrillt und verlötet kommen sie dann an die FETs. Gleiches Spiel für die Massen der Taster. <gallery> anykeyx6_tastenverdrahtung.jpg | Etwas Ordnung im Chaos </gallery> Damit die Tasten beim Zusammenfügen nicht immer wieder aus ihren Löchern entwischen, kommt Klebeband von außen auf das Gehäuse. Zur Sicherheit mit Nummern beschriftet, damit mit Drehen und Spiegeln nix schief geht. Tasten eingelegt, Leitungen im Gehäuse verlegt und den Kupfer-Knäuel zusammengedrückt. Papa sagte schon immer: Salat ist gesund. Das USB-Kabel liegt fest verzurrt und sehr engem Biegeradius im Gehäuse - hält (hoffentlich). <gallery> anykeyx6_boden_und_deckel.jpg | Beide Gehäusehälften anykeyx6_deckel_verklebt.jpg | Bestückungshilfe anykeyx6_deckel_assy.jpg | Deckel mit eingelegten Komponenten </gallery> In die untere Gehäusehälfte sind die Nippel schon eingeklebt und es wird spannend: passt es? Leider sind keine Senkkopfschrauben im Haus, also bleibt es mit den verzinkten Zylinderkopf-Schrauben etwas hässlich. Oder pragmatisch. Naja, es hält - und die Tasten liegen so im Gehäuse, dass sie weder (allzu sehr) klappern noch permanent gedrückt werden. Erfolg! :) Um bei den Tasten nicht im kompletten Blindflug zu sein, ziert noch ein Label und ein paar Symbole der FontAwesome die obere Reihe. Damit sollte nun nichts mehr schief geben. =Software= ==Erster Test== Die erste Testsoftware ist in Python geschrieben und lässt einen Regenbogen durchlaufen. Der Einfachheit halber fasst sie nur eine LED gleichzeitig an: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> Sieht dann als Momentaufnahme in etwa wie folgt aus: <gallery> anykeyx6_rgb_demo.jpg | Farben, yay! </gallery> ==Der OBS-Client== Ein "echtes" Plugin für OSB Studio zu schreiben spare ich mir mangels Tiefe in C++. Stattdessen nutze ich [https://github.com/Palakis/obs-websocket obs-websocket], das eine API für C# anbietet, die extrem einfach zu bedienen ist. Für die Buttons ist eine extrem rudimentäre Klasse sehr schnell zusammengehackt. Gänzlich ohne Fehlerbehandlung. Das Auslesen der Buttons erfolgt in einem Background-Worker, der Events feuert (und beim Loslassen zusätzlich die Dauer des Drückens ermittelt), das Setzen der LED-Farben erfolgt für alle 6. Hier merkt man auch wie heiß die Nadel ist mit der gestrickt wird: Zwischen dem Schreiben der beiden "Sets" legt sich die Software für eine Millisekunde schlafen. Der Grund einst einfach die dämlich - schreibt man zu schnell, geht evtl. das erste der beiden Datenpakete in der Firmware verloren, weil die Übergabe nicht (wenn man es so nennen will) threadsafe ist. Die GUI hat lediglich einen "Connect"-Button, der nur gedrückt werden sollte, wenn OBS läuft und die Hardware verbunden ist. Die Konfiguration ist ebenfalls eher grundlegend und in AnykeyOBS.exe.config zu finden. Hier kann für jede Taste die Aktiv/Inaktiv-Farbe als Hex-Code (oder named color, ungetestet) abgelegt werden, die Funktion definiert und ein Argument für diese Funktion angegeben werden. Zum Zuordnen einer Szene packt man in die Funktion "Scene" und schreibt den zugehörigen Szenen-Namen ins Argument. Für die Aufnahme heißt die Funktion "Record" und als Argument kann "Toggle", "Start" und "Stop" definiert werden. Streaming wird noch nicht unterstützt. Aus mir nicht ganz verständlichen Gründen kann der Zustand des Streamings/Recordings nur über Events ermittelt werden, dadurch bleibt die Taste mit entsprechender Zuordnung beim Start des Programms orange. Dies ist auch die (fest hinterlegte) Farbe für Übergänge zwischen Aufnahme und keine Aufnahme. Ein weiteres Feature ist das Abbrechen einer Funktion - Grundsätzlich werden die Aktionen erst beim Loslassen des Tasters getriggert - außer man drückt diesen länger als eine Sekunde. In diesem Fall wird die Aktion abgebrochen. Insgesamt kann man die Software allerhöchstens als Proof of Concept bezeichnen. Es funktioniert, irgendwie. ===Feuerprobe=== Mittlerweile durfte ich meine Schwester sogar besuchen, um ihr die Hardware zu geben. yay! Das Einrichten fand aber trotzdem online statt. obs-websockt installiert, AnykeyOBS aufs Tablet und: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Mist. Die vermutliche Ursache ist schnell gefunden: Bei manchen USB-Geräten kann der Name nicht gelesen werden. Eine Packung try-catch auf das Problem geworfen und eine Prise <code>Console.WriteLine</code>s und das Programm bleib nach dem Klick auf "Connect" geöffnet. "Leuchten die Knöppe?" - "Oh mann, wie geil" - "Also ja?". Danach hörte ich nur noch wildes Klicken. Ich glaube, das Teil gefällt. Und so sieht es aus: [[Datei:anykeyx6_demo.mp4]] =Fazit= Wo fange ich an? Beim Guten, beim Schlechten oder bei den Sachen, für die ich mich schäme? Unterm Strich: für eine sehr hemdsärmelig zusammengestrickte Hardware sieht es (ohne dass ich mich selbst loben möchte) ganz ordentlich aus. Schlimm wird es erst, wenn man unter die Haube schaut. Das dafür aber auch konsequent. Das Gute: * Meine Schwester hat etwas, das ihr hoffentlich die Arbeit etwas erleichtert * Ich habe wieder einiges in Sachen 3D-Druck gelernt * Es hat ziemlich viel Spaß gemacht * Alles ist bunt Das Schlechte: * Decoupling, welches Decoupling? * LEDs ** Nicht sonderlich hell ** Flackern bei USB-Traffic (durch INT0) ** In dunkler Umgebung zu hell und bei Tageslicht schlecht sichtbar * Das Setzen von LEDs und Tastendrücke können verschluckt werden * Taster ** Können auch von der Gehäuseunterseite betätigt werden ** Relativ laut (im Video hörbar) ** Wackeln, sind schief und haben keine Führung * Software ** An allen Ecken und Enden rudimentär, wenn etwas ausfällt, funktioniert erst einmal nichts ** Kein automatisches Verbinden mit OBS und der Hardware ** Keine GUI für die Konfiguration ** So gut wie keine Funktionen in OBS unterstützt ** Außer OBS-Steuerung keine weiteren Funktionen * Keine Standby-States =Downloads= * [[Datei:Anykeyx6.zip]] SketchUp-Dateien, zugehörige STLs, Firmware und C#-Software um mit OBS zu sprechen. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] e0721881f3a4901ce372e2e10c155b7897321435 1585 1584 2020-05-10T20:49:41Z Chris 2 /* Tasten */ Formulierung wikitext text/x-wiki [[Datei:anykeyx6_komplett.jpg|thumb|Fertig aufgebaute Hardware (Farben leicht retuschiert)]] Meine Schwester ist Lehrerin. Ein Job, um den ich sie nicht beneide - gerade in 2020. Hier in Bayern fängt (Stand Anfang Mai) das Leben an der Schule langsam wieder an, parallel zum Unterricht in den Schulen müssen jedoch die daheim bleibenden Kinder noch unterrichtet werden. Wenn man die eigene Arbeit ernst nimmt, ist das kein Spaß. Klar, man könnte für das Eigenstudium einfach Arbeitsblätter über den Zaun werfen und auf Seiten in den Büchern verweisen, aber wenn ich da an meine eigene Schulzeit und die eher extrinsische Motivation denke... Obwohl meine Schwester schon sehr viel digital hat, braucht Unterricht (gerade bei Sprachen) auch jemanden, der/die vor der Klasse spricht und natürlich ist eigenständiges Lernen für viele nicht ganz einfach. Aus diesem Grund hat meine Schwester angefangen, Videos zu machen. Vorerst nur mit ausgedruckten Blättern und dem Handy auf dem Stativ. Um Ihre digitalen Materialien besser nutzen zu können, fragte sie dann doch mal nach einem screen recorder. [https://obsproject.com/ OBS] war schnell installiert und eingerichtet. Blöd nur, dass sie keinen zweiten Monitor (bzw. Displayport-Adapter) für ihr MS Surface hat. Damit ihre Schüler sie auch mal sehen können (oder auch mal "Tafelunterricht" zu machen), habe ich ihr mehrere Szenen in OBS eingerichtet: * Bildschirmaufnahme * Bildschirmaufnahme + Kamera in der Ecke * Kamera Blöd ist nur, dass sie ohne besagten zweiten Bildschirm für jede Aktion OBS in den Vordergrund holen muss. Zwar kann man dort auch globale Hotkeys anlegen, aber ohne vollständige Tastatur läuft man sehr schnell Gefahr, Doppelbelegungen zu bekommen und dadurch sehr merkwürdiges Verhalten am PC zu haben. Gleichzeitig sieht man nicht, was OBS nun tatsächlich macht. Ja, man kann eine Fernbedienung für OBS auf dem Tablet oder Smartphone installieren, aber das schafft eigentlich nur mehr Probleme als es löst, zumal man die (freien) Clients, die ich auf Anhieb gefunden hab für jede Session neu konfigurieren muss. Zudem muss das Gerät am Laufen halten und kann die Tasten nicht erfühlen. Das lenkt unnötig ab und erhöht auch die Akzeptanz nicht wirklich. Auch fertige Lösungen wie das Elgato Stream Deck ist für die (hoffentlich) kurze Nutzungsdauer unverhältnismäßig teuer. Gleichzeitig sitzt hier ein Ingenieur herum, der aufgrund der aktuellen Situation erst einmal Gleitzeit abbaut. =Die Idee= Da kann man doch was basteln. Ein paar Taster, ein paar LEDs, ein bisschen Firmware und noch ein paar Zeilen Code auf dem PC. Was soll daran so aufwändig sein? Um eines vorweg zu nehmen: Übers Ziel hinausschießen, das kann daran aufwändig werden. Ziel ist, 6-8 bunt beleuchtete Taster zu haben, die in OBS eingebunden werden können. Der Mikrocontroller ist schnell gefunden. Um nicht zu weit von den Codebeispielen von [https://www.obdev.at/products/vusb/index-de.html V-USB] zu sein, soll ein oller ATmega8 zum Einsatz kommen. Weil ich schon länger was mit intelligenten LEDs machen wollte, liegt schon viel zu lange ein Streifen mit WS2812B herum. Der Plan war, diese – womöglich sogar noch auf dem Streifen – auf Taster zu kleben. Natürlich muss der [[wpde:Woman acceptance factor|WAF]] auch halbwegs passen, deshalb ist ein nicht zu schäbiges Gehäuse angesagt. 3D-Drucker sei dank bin ich auch dazu (zumindest seitens der Ausstattung) in der Lage. =Elektronik= Die Ernüchterung kam schneller als erwartet. Dass die Ansteuerung der LEDs zeitkritisch ist, wusste ich. Dass das auch für V-USB gilt, ebenfalls. Dass man beides nicht so einfach kombinieren kann, würde dann sehr schnell klar. Der USB-Stack braucht zwingend einen Pin-Interrupt, für die Ansteuerung der LEDs muss dieser aber abgeschaltet werden – sonst blinkt alles wie ein Weihnachtsbaum auf LSD. Tim (aka cpldcpu) hat sich die Mühe gemacht, V-USB mit [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling zu ermöglichen] - gleichzeitig sogar mit entsprechender LED. Den Weg wollte ich nicht gehen, weil das potenziell an anderen Stellen schmerzhaft werden könnte. Ok, was nun? Ein Coprozessor, der UART/I²C auf das LED-Protokoll umwandelt? Eigentlich wollte ich kein Mehrprozessor-System bauen – und auch hier bleibt das Problem mit Interrupts vs. keine Interrupts, auch durch die Einschränkungen durch USI dürfte das noch etwas unentspannter sein. Da ist guter Rat teuer. Auf einfarbige LEDs wollte ich aber auch nicht zurückgehen. ==LED-Treiber== 6 RGB-LEDs mit PWM anzusteuern, braucht es 18 PWM-Kanäle. Das hat glaube ich kein AVR8. ich habe zwar noch einen PCA9685 herumliegen, der aber auch nur 16 Kanäle bereitstellt. Zudem nimmt das Teil mit seinem Breakout-Board relativ viel Platz ein. Zu viel für das, was ich vor dem inneren Auge habe. Habe ich 18 Kanäle geschrieben? Jein. Betreibt man Multiplexing, reichen zwischen 3 und 6. Schlussendlich habe ich mich dafür entschieden, die Farben in den Multiplex zu nehmen und den PWM pro Taste laufen zu lassen - mit entsprechenden Einbußen der Helligkeit (ein Drittel). Aber wo bekommt man an einem ATmega8 6 synchrone PWM-Kanäle her? Ganz einfach: gar nicht. Zumindest in Hardware - anders schaut es in Software aus, wo es auch keine richtige PWM ist, sondern eher eine Pulsleistungsmodulation (kurz PDM - einen passenden Begriff konnte ich finden, daher die Neukreation), wie sie 2011 auf der [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite] schon beschrieben wurde. Um es kurz zu beschreiben: bei gewöhnlicher PWM gibt es für jeden Kanal zwei Schaltzeitpunkte, von denen einer pro Kanal individuell ist (da er den Helligkeitswert vorgibt). Hat man n Kanäle, gibt es n Zeitpunkte, die man möglichst zielgenau treffen muss. Gerade wenn diese nah beieinander liegen, kann das zu Timingproblemen führen. Der hier verwendete Dimmer funktioniert anders. Man muss dabei bedenken, dass es beim Dimmen von LEDs relativ egal ist, ob sie über einen Zyklus am Stück an sind, oder ob sie zwischendurch ausgeschaltet werden - wichtig ist unterm Strich nur, wie viel sie im im Laufe eines Zyklus aktiv sind. Bei einer Auflösung von b bit gibt es bei dieser Methode b Zeitpunkte - ganz egal wie viele Kanäle man verwendet und: deren Timing ist fest. Zudem sind diese sind zeitlich immer mit Faktor 2 voneinander getrennt. Nun schaltet man den Kanal immer dann an, wenn im Helligkeitswert das "Bit" des zugehörigen Zeitschlitzes aktiv ist. Da es visuell deutlich besser als mit Text funktioniert, hier mal zwei Beispiele mit einer Modulation mit 3 Bit. Die Wertigkeit steht links, die An-Zeiten entsprechen den grünen Blöcken (deren X-Achse der Zeit entspricht) und die nötigen Interrupts sind mit roten Pfeilen markiert: <gallery> anykeyx6_pwm.png | Pulsweitenmodulation anykeyx6_plm.png | Pulsleistungsmodulation </gallery> Betrachtet man die aktive Fläche der einzelnen Helligkeitswerte, kommt man auf das gleiche - nur dass die PDM deutlich ressourcenschonender ist. Dazu kommt der Effekt, dass durch das "Zerhacken" der PWM die LEDs mit einer höheren Frequenz flackern (auch wenn sie variiert). Dadurch wird der Stroboskop-Effekt verringert - des einen Freud ist des anderen Leid: achtet man auf EMV, wird es and er Stelle unangenehmer. Aber genug dazu. Aufgrund des Multiplexing gibt es, wie oben beschrieben, nur ein Drittel an Helligkeit. Die meisten LEDs halten bei pulsförmiger Ansteuerung deutlich mehr Strom als im Dauerbetrieb aus weil der limitierende Faktor die Erwärmung ist. Da die LEDs (im 5050-Gehäuse) für den Aufbau von einem LED-Streifen "geerntet" wurden, habe ich kein Datenblatt zur Komponente, aber Wissen: z. B. kommt für den roten Strang ein 330 Ohm-Widerstand zum Einsatz, bei 12 V und 3 roten LEDs in Reihe mit ca. 1,85 V Vorwärtsspannung sind das etwa 20 mA. Ohne weitere Infos zu maximalen Strömen und weil die Helligkeit eigentlich reichen sollte, bin ich bei diesem Strom geblieben. ==Taster== Die Taster kommen direkt an IOs und sind gegen Masse verschaltet. Eine rudimentäre Entprellung wird in Software gemacht. ==USB== Die USB-Beschaltung entspricht weitestgehend der aus den Beispielen von Objective Development. Aus reiner Faulheit habe ich die Schutzbeschaltung vom [[USB-Fußtaster]] übernommen. Sprichwörtlich: Die nötigen Bauteile bestückt und die Leiterkarte auf die passende Größe gestutzt. ==Schaltplan== Die gesamte Schaltung ist also relativ einfach. Als FETs für die LEDs kommen BSS84 (p-Kanal, aufseiten der Anoden) und BSS138 (n-Kanal, aufseiten der Kathoden) zum Einsatz. Aufgrund der Komplexität reicht es als Handskizze: <gallery> anykeyx6_sch.png | Schaltplan - unbekannter Künstler, 2020, digital </gallery> =Firmware= Die Firmware ist erstaunlich einfach, zumal ich mich nicht sonderlich bemüht habe. Die LEDs werden mit der oben beschriebenen Methode (in leddrv.c) angesteuert, wobei zusätzlich noch eine Fading-Funktion zum Einsatz kommt. Das entlastet den USB-Stack und verringert das Flackern (siehe weiter unten) Die Tasten werden (sofern die PWM nicht höhere Priorität hat) jede Millisekunde abgefragt (<code>buttons_tick()</code>) und wenn der Pegel low (Taste gedrückt) ist, ein Zähler inkrementiert. Bei High-Pegel wird der Zähler auf 0 zurückgesetzt. Ist der Zähler größer als 10, gilt die entsprechende Taste gedrückt. Alle Buttons in einem Byte können über die Methode <code>buttons_values()</code> abgefragt werden. In Sachen USB wird ein Out-Report (PC -> Device) mit Netto 16 Byte und ein In-Report mit Netto 8 Byte (Device -> PC) verwendet. Der Out-Report dient zum Setzen der LEDs und sieht wie folgt aus: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index der LED (1-6) * <span class="hb2">Rx</span>: Rot-Wert der LED (0 ... 255) * <span class="hb3">Gx</span>: Grün-Wert der LED (0 ... 255) * <span class="hb4">Bx</span>: Blau-Wert der LED (0 ... 255) * <span class="hb5">Tx</span>: Dauer für den Übergang (0 ... 255, in 5 ms-Schritten) Es können somit 3 Farben gleichzeitig geschrieben werden, Index 0 wird nicht verwendet, da es üblicherweise der Init-Wert für Arrays ist und somit nicht versehentlich die Farbe einer Taste gesetzt wird. Der In-Report ist denkbar einfach, im ersten Byte steht das Bit-Muster der aktuell gedrückten Taster: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> Der Report wird bei jeder Änderung des Zustands der Taster gesendet. Das ist in mehrerlei Hinsicht nicht ganz ideal, da zum einen der Initiale Zustand (nach Öffnen des Devices) nicht ermittelt werden kann und falls doch mal ein USB-Paket verloren geht, verpasst man Tastendrücke. Aber: es musste schnell gehen. =Mechanik= Die Mechanik ist (zumindest für mich als Neuling in Sachen Design und 3D-Druck) ein Stück aufwändiger. Einfach nur die Leiterkarte auf den Tisch zu knallen geht hier nicht, es muss nicht wie aus dem Ei gepellt aussehen, aber nicht nur aus der Kategorie "form follows function" sein. Um schnell voran zu kommen, kam das MS Paint im 3D-Design zum Einsatz: SketchUp. Mit allen Einschränkungen und fehlender Parametrisierung bin ich darin leider noch immer am schnellsten, etwas für den Druck vorzubereiten. ==Tasten== Mit ein bisschen Zeichnen in 2D-Software stellte sich heraus, dass rechteckige Tasten mit 15 mm Breite und Höhe, einer Abrundung mit Radius 2,5 mm und einem Abstand von 5 mm zueinander eine angenehme Haptik aufweisen. Ein erstes Muster mit Kragen (damit die Taste nicht durchs Gehäuse fällt) aus transparentem PLA, (wenn ich mich richtig erinnere) 50 % Infill und konzentrischem Top/Bottom-Pattern (in Cura gesliced) ist schnell gedruckt und sieht, nachdem es mit Farbe beschmiert wurde um zu sehen wie dicht der Druck ist, auch nach dem Reinigen versaut aus. Licht geht durch, sieht aber eher bescheiden aus: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Ausleuchtung bei konzentrischem Druck </gallery> Als nächstes kommt die Frage: wie die LEDs und Taster montieren? um das mechanische Design zu vereinfachen, habe ich die Idee verfolgt, möglichst Gleichteile zu verwenden. In meinen letzten Leiterkarten-Bestellungen habe ich im Waste immer 1x1 mm Kupferflächen im 1,27 mm-Raster platziert, ein Streifen damit ist etwa 9,6 mm breit (bei 1,6 mm Materialdicke) - eine gute Größe für diese Anwendung. LED auf die eine Seite, Taster auf die andere und eine Idee, für die mich die Mechaniker in der Arbeit (völlig zu Recht) vermutlich nicht mehr anschauen würden: Constraining auf zwei Bezugsebenen. Normalerweise strebt man an, dass sich die Toleranzen von einer Seite aus ausbreiten, damit man die Toleranzketten in Griff halten kann. Würde hier heißen: Die Tasten sind auf die Gehäusefront referenziert und dementsprechend müssen die Taster auch an einer Ebene montiert werden, deren Toleranz sich auf die Front bezieht. Bei mir sollen die Taster aber gegen die Bodenplatte drücken. Mit vielen Nachteilen. Da es sich aktuell allerdings um ein Einzelstück handelt: Egal. Das Platinchen mit LED vorne und Taster hinten wird einfach in eine Nut im Taster eingeschoben. Bis auf einen kleinen (reproduzierbaren) Druckfehler funktioniert das prächtig. Hier die verschiedenen Designiterationen: <gallery> anykeyx6_taste_iterationen.jpg | Iterationen der Tasten 1 bis 5.5 anykeyx6_sketchup_taste_seite.png | Finales Modell der Tasten von der Seite anykeyx6_sketchup_taster_unten.png | und von unten anykeyx6_taste_einzelteile.jpg | Einzelteile der Tasten (der Taster fehlt) anykeyx6_taste_LED.jpg | Leiterkarte in die Taste eingeschoben </gallery> Mit Infill auf 100 % und der Tasterfront auf dem Druckbett entsteht eine relativ schöne Oberfläche. Da Concentric Top/Bottom-Pattern ein Kreuz in der Diagonale erzeugt hat, bin ich auf "Lines" umgestiegen, das die Taster, gemeinsam mit dem konzentrischen Rahmen fast schon "wie gekauft" aussehen lässt. Um eine bessere Farbmischung zu erzeugen (und die Taster eine eigenwillige Streuwirkung haben), habe ich etwas Band aus meinem Beschriftungsgerät (Wenn es wichtig ist: Brother P-touch) hinter den Taster geklebt. Dadurch wird die Ausleuchtung der drei LED-Kristalle zumindest ein bisschen homogener: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Zum Vergleich nochmal das Bild von oben (konzentrischer Druck) anykeyx6_beleuchtung_diffusor.jpg | links ohne Folie, rechts mit </gallery> Insgesamt hat das Sandwich eine Höhe von 12,4 mm - 0,25 mm weniger, wenn der Taster gedrückt ist. Der Kragen ist 2,5 mm nach innen versetzt. Das, plus die Dicke der Gehäuseteile, wird die Gesamtdicke des Geräts. =Gehäuse= Mit den Maßen der Tasten geht es los, wobei die Ausschnitte für diese um 0,25 mm in alle Richtungen erweitert wurden. Das bringt zwar etwas Spiel, aber bevor der Cutter angesetzt oder nochmals gedruckt werden muss, dürfen die Tasten eher ein bisschen wackeln - zumal es bei den ersten Tastern ordentlich Elefantenfüße gab. Mit einem Überstand von 7,5 mm von der Kante der Taster zu den Gehäusewänden in drei Richtungen und etwas mehr (17,5 mm) in die vierte Richtung - irgendwo muss ja die Elektronik hin - ist das Gehäuse relativ kompakt. Im inneren befinden sich zwischen den Tastern 4 mm hohe Wände - nicht zum Ausrichten, sondern vielmehr um Streulicht zwischen den Tastern zu vermeiden. Damit sich das Gehäuse nicht durchbiegt und dadurch versehentlich mehrere Taster auf einmal betätigt werden, befinden sich in den Kreuzungspunkten der Taster Erhöhungen, die die Stabilität in Z-Richtung erhöhen. Um Material und vor allem Druckzeit zu sparen, gab es zwei abgeschnittene Druckmuster, die man dank transparentem Filament auf weißem Grund fast nicht sieht: <gallery> anykeyx6_druckmuster_deckel.jpg | Druckmuster für die Aufnahme der Tasten </gallery> Als Zugentlastung des fest installierten USB-Kabels befindet sich hinter dem U-förmigen Ausschnitt eine kleine Rampe und ein Loch, durch den ein Kabelbinder passt. Die Rampe dient lediglich dazu, dass der Kabelbinder die untere Gehäusehälfte nicht nach unten drückt. Man könnte mutmaßen, dass durch die Druckschichten bedingte Treppenstruktur die Leitung sogar ein bisschen verhakt wird. 3 Löcher, durch die M2,5-Schrauben passen, dienen zur Befestigung der Bodenplatte. Insgesamt gab es 4 Iterationen, wobei nur zwei den Weg auf den Drucker gefunden haben - und das auch nur, weil sich das erste Druckteil vom Druckbett abgelöst und dadurch unschön verzogen hat. Anscheinend sind die STL-Daten nicht ganz sauber, wodurch das Modell wohl etwas in der Luft hängt. Durch einen Microstep von -0,001 in Z-Richtung wurde das Druckergebnis besser, aber die erste Lage ist trotzdem noch etwas lückig... <gallery> anykeyx6_sketchup_deckel.png | 3D-Modell des Deckels anykeyx6_deckel_vergurkt.jpg | Der erste Versuch (vergurkt) anykeyx6_Deckel.jpg | Der bessere Druck. </gallery> Das untere Gehäuseteil sind eigentlich 7 Teile und brauchte keine Revision (aber einen kleinen Eingriff mit dem Skalpell). Die Komplexität ist auch deutlich geringer. Auffallend sind zunächst die 4 "Kamine" - die Idee dahinter ist, Muttern einzulegen und diese mit dem oberen Gehäuseteil zu verschrauben. Das ganze ist (eher unbeabsichtigt) auf Pressung designed, sowohl für die Mutter, als auch in Richtung anderes Gehäuseteil. Immerhin rutscht nichts. An den Positionen der Taster befinden sich Sacklöcher/Kerben - aus einem sehr einfachen Grund: Material und Druckzeit sparen. Die Bodenplatte soll in weiten Teilen dick genug sein, dass sie stabil ist aber auf keinen Fall ein zweites Mal gedruckt werden muss. Um die Taster in der Höhe einzupassen, werden kleine Distanznippel eingesetzt, die klein sind und dadurch sehr schnell angepasst und gedruckt werden können. Weil ich keinen Sekundenkleber mehr da hatte, sind sie lediglich einseitig auf der Bodenplatte mit doppelseitigem Klebeband befestigt. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D-Modell der Bodenplatte anykeyx6_shim.png | Das 3D-Modell eines Nippel anykeyx6_bodenplatte_benippelt.jpg | Bodenplatte mit Muttern und Nippeln </gallery> Insgesamt war der Drucker etwa 4 Stunden beschäftigt, wobei er auch nicht mit maximaler Geschwindigkeit lief. Die Materialkosten liegen (ohne Probestücke und Fehldrucke) bei etwa 50 cent wenn ich mich nicht täusche, also nicht wirklich der Rede wert. =Zusammenbau= Ursprünglich habe ich einen Atmega8 im DIP-Gehäuse vorgesehen. Da es aber doch ein bisschen eng geworden wäre, kam dann doch einer im TQFP-Gehäuse zum Einsatz. Neben dem Mikrocontroller finden auch die 9 Transistoren für die LED-Ansteuerung Platz auf der Selfmade-Punktrasterplatine: <gallery> anykeyx6_platine.jpg | Bestückte Leiterkarte. </gallery> Die LED-Tasten bekommen gehörig lange Anschlussleitungen aus Kupferlackdraht, die durchgepiepst und auf passend beschriftete Klebebandstreifen landen. Miteinander verdrillt und verlötet kommen sie dann an die FETs. Gleiches Spiel für die Massen der Taster. <gallery> anykeyx6_tastenverdrahtung.jpg | Etwas Ordnung im Chaos </gallery> Damit die Tasten beim Zusammenfügen nicht immer wieder aus ihren Löchern entwischen, kommt Klebeband von außen auf das Gehäuse. Zur Sicherheit mit Nummern beschriftet, damit mit Drehen und Spiegeln nix schief geht. Tasten eingelegt, Leitungen im Gehäuse verlegt und den Kupfer-Knäuel zusammengedrückt. Papa sagte schon immer: Salat ist gesund. Das USB-Kabel liegt fest verzurrt und sehr engem Biegeradius im Gehäuse - hält (hoffentlich). <gallery> anykeyx6_boden_und_deckel.jpg | Beide Gehäusehälften anykeyx6_deckel_verklebt.jpg | Bestückungshilfe anykeyx6_deckel_assy.jpg | Deckel mit eingelegten Komponenten </gallery> In die untere Gehäusehälfte sind die Nippel schon eingeklebt und es wird spannend: passt es? Leider sind keine Senkkopfschrauben im Haus, also bleibt es mit den verzinkten Zylinderkopf-Schrauben etwas hässlich. Oder pragmatisch. Naja, es hält - und die Tasten liegen so im Gehäuse, dass sie weder (allzu sehr) klappern noch permanent gedrückt werden. Erfolg! :) Um bei den Tasten nicht im kompletten Blindflug zu sein, ziert noch ein Label und ein paar Symbole der FontAwesome die obere Reihe. Damit sollte nun nichts mehr schief geben. =Software= ==Erster Test== Die erste Testsoftware ist in Python geschrieben und lässt einen Regenbogen durchlaufen. Der Einfachheit halber fasst sie nur eine LED gleichzeitig an: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> Sieht dann als Momentaufnahme in etwa wie folgt aus: <gallery> anykeyx6_rgb_demo.jpg | Farben, yay! </gallery> ==Der OBS-Client== Ein "echtes" Plugin für OSB Studio zu schreiben spare ich mir mangels Tiefe in C++. Stattdessen nutze ich [https://github.com/Palakis/obs-websocket obs-websocket], das eine API für C# anbietet, die extrem einfach zu bedienen ist. Für die Buttons ist eine extrem rudimentäre Klasse sehr schnell zusammengehackt. Gänzlich ohne Fehlerbehandlung. Das Auslesen der Buttons erfolgt in einem Background-Worker, der Events feuert (und beim Loslassen zusätzlich die Dauer des Drückens ermittelt), das Setzen der LED-Farben erfolgt für alle 6. Hier merkt man auch wie heiß die Nadel ist mit der gestrickt wird: Zwischen dem Schreiben der beiden "Sets" legt sich die Software für eine Millisekunde schlafen. Der Grund einst einfach die dämlich - schreibt man zu schnell, geht evtl. das erste der beiden Datenpakete in der Firmware verloren, weil die Übergabe nicht (wenn man es so nennen will) threadsafe ist. Die GUI hat lediglich einen "Connect"-Button, der nur gedrückt werden sollte, wenn OBS läuft und die Hardware verbunden ist. Die Konfiguration ist ebenfalls eher grundlegend und in AnykeyOBS.exe.config zu finden. Hier kann für jede Taste die Aktiv/Inaktiv-Farbe als Hex-Code (oder named color, ungetestet) abgelegt werden, die Funktion definiert und ein Argument für diese Funktion angegeben werden. Zum Zuordnen einer Szene packt man in die Funktion "Scene" und schreibt den zugehörigen Szenen-Namen ins Argument. Für die Aufnahme heißt die Funktion "Record" und als Argument kann "Toggle", "Start" und "Stop" definiert werden. Streaming wird noch nicht unterstützt. Aus mir nicht ganz verständlichen Gründen kann der Zustand des Streamings/Recordings nur über Events ermittelt werden, dadurch bleibt die Taste mit entsprechender Zuordnung beim Start des Programms orange. Dies ist auch die (fest hinterlegte) Farbe für Übergänge zwischen Aufnahme und keine Aufnahme. Ein weiteres Feature ist das Abbrechen einer Funktion - Grundsätzlich werden die Aktionen erst beim Loslassen des Tasters getriggert - außer man drückt diesen länger als eine Sekunde. In diesem Fall wird die Aktion abgebrochen. Insgesamt kann man die Software allerhöchstens als Proof of Concept bezeichnen. Es funktioniert, irgendwie. ===Feuerprobe=== Mittlerweile durfte ich meine Schwester sogar besuchen, um ihr die Hardware zu geben. yay! Das Einrichten fand aber trotzdem online statt. obs-websockt installiert, AnykeyOBS aufs Tablet und: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Mist. Die vermutliche Ursache ist schnell gefunden: Bei manchen USB-Geräten kann der Name nicht gelesen werden. Eine Packung try-catch auf das Problem geworfen und eine Prise <code>Console.WriteLine</code>s und das Programm bleib nach dem Klick auf "Connect" geöffnet. "Leuchten die Knöppe?" - "Oh mann, wie geil" - "Also ja?". Danach hörte ich nur noch wildes Klicken. Ich glaube, das Teil gefällt. Und so sieht es aus: [[Datei:anykeyx6_demo.mp4]] =Fazit= Wo fange ich an? Beim Guten, beim Schlechten oder bei den Sachen, für die ich mich schäme? Unterm Strich: für eine sehr hemdsärmelig zusammengestrickte Hardware sieht es (ohne dass ich mich selbst loben möchte) ganz ordentlich aus. Schlimm wird es erst, wenn man unter die Haube schaut. Das dafür aber auch konsequent. Das Gute: * Meine Schwester hat etwas, das ihr hoffentlich die Arbeit etwas erleichtert * Ich habe wieder einiges in Sachen 3D-Druck gelernt * Es hat ziemlich viel Spaß gemacht * Alles ist bunt Das Schlechte: * Decoupling, welches Decoupling? * LEDs ** Nicht sonderlich hell ** Flackern bei USB-Traffic (durch INT0) ** In dunkler Umgebung zu hell und bei Tageslicht schlecht sichtbar * Das Setzen von LEDs und Tastendrücke können verschluckt werden * Taster ** Können auch von der Gehäuseunterseite betätigt werden ** Relativ laut (im Video hörbar) ** Wackeln, sind schief und haben keine Führung * Software ** An allen Ecken und Enden rudimentär, wenn etwas ausfällt, funktioniert erst einmal nichts ** Kein automatisches Verbinden mit OBS und der Hardware ** Keine GUI für die Konfiguration ** So gut wie keine Funktionen in OBS unterstützt ** Außer OBS-Steuerung keine weiteren Funktionen * Keine Standby-States =Downloads= * [[Datei:Anykeyx6.zip]] SketchUp-Dateien, zugehörige STLs, Firmware und C#-Software um mit OBS zu sprechen. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] 52402c44da6496704f55cf7cccf479be53301d34 1587 1585 2020-05-11T18:22:35Z Chris 2 Der erste Artikel auf Englisch wikitext text/x-wiki ''There's also an [[Anykey_x6/en|English translation]] of this article'' [[Datei:anykeyx6_komplett.jpg|thumb|Fertig aufgebaute Hardware (Farben leicht retuschiert)]] Meine Schwester ist Lehrerin. Ein Job, um den ich sie nicht beneide - gerade in 2020. Hier in Bayern fängt (Stand Anfang Mai) das Leben an der Schule langsam wieder an, parallel zum Unterricht in den Schulen müssen jedoch die daheim bleibenden Kinder noch unterrichtet werden. Wenn man die eigene Arbeit ernst nimmt, ist das kein Spaß. Klar, man könnte für das Eigenstudium einfach Arbeitsblätter über den Zaun werfen und auf Seiten in den Büchern verweisen, aber wenn ich da an meine eigene Schulzeit und die eher extrinsische Motivation denke... Obwohl meine Schwester schon sehr viel digital hat, braucht Unterricht (gerade bei Sprachen) auch jemanden, der/die vor der Klasse spricht und natürlich ist eigenständiges Lernen für viele nicht ganz einfach. Aus diesem Grund hat meine Schwester angefangen, Videos zu machen. Vorerst nur mit ausgedruckten Blättern und dem Handy auf dem Stativ. Um Ihre digitalen Materialien besser nutzen zu können, fragte sie dann doch mal nach einem screen recorder. [https://obsproject.com/ OBS] war schnell installiert und eingerichtet. Blöd nur, dass sie keinen zweiten Monitor (bzw. Displayport-Adapter) für ihr MS Surface hat. Damit ihre Schüler sie auch mal sehen können (oder auch mal "Tafelunterricht" zu machen), habe ich ihr mehrere Szenen in OBS eingerichtet: * Bildschirmaufnahme * Bildschirmaufnahme + Kamera in der Ecke * Kamera Blöd ist nur, dass sie ohne besagten zweiten Bildschirm für jede Aktion OBS in den Vordergrund holen muss. Zwar kann man dort auch globale Hotkeys anlegen, aber ohne vollständige Tastatur läuft man sehr schnell Gefahr, Doppelbelegungen zu bekommen und dadurch sehr merkwürdiges Verhalten am PC zu haben. Gleichzeitig sieht man nicht, was OBS nun tatsächlich macht. Ja, man kann eine Fernbedienung für OBS auf dem Tablet oder Smartphone installieren, aber das schafft eigentlich nur mehr Probleme als es löst, zumal man die (freien) Clients, die ich auf Anhieb gefunden hab für jede Session neu konfigurieren muss. Zudem muss das Gerät am Laufen halten und kann die Tasten nicht erfühlen. Das lenkt unnötig ab und erhöht auch die Akzeptanz nicht wirklich. Auch fertige Lösungen wie das Elgato Stream Deck ist für die (hoffentlich) kurze Nutzungsdauer unverhältnismäßig teuer. Gleichzeitig sitzt hier ein Ingenieur herum, der aufgrund der aktuellen Situation erst einmal Gleitzeit abbaut. =Die Idee= Da kann man doch was basteln. Ein paar Taster, ein paar LEDs, ein bisschen Firmware und noch ein paar Zeilen Code auf dem PC. Was soll daran so aufwändig sein? Um eines vorweg zu nehmen: Übers Ziel hinausschießen, das kann daran aufwändig werden. Ziel ist, 6-8 bunt beleuchtete Taster zu haben, die in OBS eingebunden werden können. Der Mikrocontroller ist schnell gefunden. Um nicht zu weit von den Codebeispielen von [https://www.obdev.at/products/vusb/index-de.html V-USB] zu sein, soll ein oller ATmega8 zum Einsatz kommen. Weil ich schon länger was mit intelligenten LEDs machen wollte, liegt schon viel zu lange ein Streifen mit WS2812B herum. Der Plan war, diese – womöglich sogar noch auf dem Streifen – auf Taster zu kleben. Natürlich muss der [[wpde:Woman acceptance factor|WAF]] auch halbwegs passen, deshalb ist ein nicht zu schäbiges Gehäuse angesagt. 3D-Drucker sei dank bin ich auch dazu (zumindest seitens der Ausstattung) in der Lage. =Elektronik= Die Ernüchterung kam schneller als erwartet. Dass die Ansteuerung der LEDs zeitkritisch ist, wusste ich. Dass das auch für V-USB gilt, ebenfalls. Dass man beides nicht so einfach kombinieren kann, würde dann sehr schnell klar. Der USB-Stack braucht zwingend einen Pin-Interrupt, für die Ansteuerung der LEDs muss dieser aber abgeschaltet werden – sonst blinkt alles wie ein Weihnachtsbaum auf LSD. Tim (aka cpldcpu) hat sich die Mühe gemacht, V-USB mit [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling zu ermöglichen] - gleichzeitig sogar mit entsprechender LED. Den Weg wollte ich nicht gehen, weil das potenziell an anderen Stellen schmerzhaft werden könnte. Ok, was nun? Ein Coprozessor, der UART/I²C auf das LED-Protokoll umwandelt? Eigentlich wollte ich kein Mehrprozessor-System bauen – und auch hier bleibt das Problem mit Interrupts vs. keine Interrupts, auch durch die Einschränkungen durch USI dürfte das noch etwas unentspannter sein. Da ist guter Rat teuer. Auf einfarbige LEDs wollte ich aber auch nicht zurückgehen. ==LED-Treiber== 6 RGB-LEDs mit PWM anzusteuern, braucht es 18 PWM-Kanäle. Das hat glaube ich kein AVR8. ich habe zwar noch einen PCA9685 herumliegen, der aber auch nur 16 Kanäle bereitstellt. Zudem nimmt das Teil mit seinem Breakout-Board relativ viel Platz ein. Zu viel für das, was ich vor dem inneren Auge habe. Habe ich 18 Kanäle geschrieben? Jein. Betreibt man Multiplexing, reichen zwischen 3 und 6. Schlussendlich habe ich mich dafür entschieden, die Farben in den Multiplex zu nehmen und den PWM pro Taste laufen zu lassen - mit entsprechenden Einbußen der Helligkeit (ein Drittel). Aber wo bekommt man an einem ATmega8 6 synchrone PWM-Kanäle her? Ganz einfach: gar nicht. Zumindest in Hardware - anders schaut es in Software aus, wo es auch keine richtige PWM ist, sondern eher eine Pulsleistungsmodulation (kurz PDM - einen passenden Begriff konnte ich finden, daher die Neukreation), wie sie 2011 auf der [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite] schon beschrieben wurde. Um es kurz zu beschreiben: bei gewöhnlicher PWM gibt es für jeden Kanal zwei Schaltzeitpunkte, von denen einer pro Kanal individuell ist (da er den Helligkeitswert vorgibt). Hat man n Kanäle, gibt es n Zeitpunkte, die man möglichst zielgenau treffen muss. Gerade wenn diese nah beieinander liegen, kann das zu Timingproblemen führen. Der hier verwendete Dimmer funktioniert anders. Man muss dabei bedenken, dass es beim Dimmen von LEDs relativ egal ist, ob sie über einen Zyklus am Stück an sind, oder ob sie zwischendurch ausgeschaltet werden - wichtig ist unterm Strich nur, wie viel sie im im Laufe eines Zyklus aktiv sind. Bei einer Auflösung von b bit gibt es bei dieser Methode b Zeitpunkte - ganz egal wie viele Kanäle man verwendet und: deren Timing ist fest. Zudem sind diese sind zeitlich immer mit Faktor 2 voneinander getrennt. Nun schaltet man den Kanal immer dann an, wenn im Helligkeitswert das "Bit" des zugehörigen Zeitschlitzes aktiv ist. Da es visuell deutlich besser als mit Text funktioniert, hier mal zwei Beispiele mit einer Modulation mit 3 Bit. Die Wertigkeit steht links, die An-Zeiten entsprechen den grünen Blöcken (deren X-Achse der Zeit entspricht) und die nötigen Interrupts sind mit roten Pfeilen markiert: <gallery> anykeyx6_pwm.png | Pulsweitenmodulation anykeyx6_plm.png | Pulsleistungsmodulation </gallery> Betrachtet man die aktive Fläche der einzelnen Helligkeitswerte, kommt man auf das gleiche - nur dass die PDM deutlich ressourcenschonender ist. Dazu kommt der Effekt, dass durch das "Zerhacken" der PWM die LEDs mit einer höheren Frequenz flackern (auch wenn sie variiert). Dadurch wird der Stroboskop-Effekt verringert - des einen Freud ist des anderen Leid: achtet man auf EMV, wird es and er Stelle unangenehmer. Aber genug dazu. Aufgrund des Multiplexing gibt es, wie oben beschrieben, nur ein Drittel an Helligkeit. Die meisten LEDs halten bei pulsförmiger Ansteuerung deutlich mehr Strom als im Dauerbetrieb aus weil der limitierende Faktor die Erwärmung ist. Da die LEDs (im 5050-Gehäuse) für den Aufbau von einem LED-Streifen "geerntet" wurden, habe ich kein Datenblatt zur Komponente, aber Wissen: z. B. kommt für den roten Strang ein 330 Ohm-Widerstand zum Einsatz, bei 12 V und 3 roten LEDs in Reihe mit ca. 1,85 V Vorwärtsspannung sind das etwa 20 mA. Ohne weitere Infos zu maximalen Strömen und weil die Helligkeit eigentlich reichen sollte, bin ich bei diesem Strom geblieben. ==Taster== Die Taster kommen direkt an IOs und sind gegen Masse verschaltet. Eine rudimentäre Entprellung wird in Software gemacht. ==USB== Die USB-Beschaltung entspricht weitestgehend der aus den Beispielen von Objective Development. Aus reiner Faulheit habe ich die Schutzbeschaltung vom [[USB-Fußtaster]] übernommen. Sprichwörtlich: Die nötigen Bauteile bestückt und die Leiterkarte auf die passende Größe gestutzt. ==Schaltplan== Die gesamte Schaltung ist also relativ einfach. Als FETs für die LEDs kommen BSS84 (p-Kanal, aufseiten der Anoden) und BSS138 (n-Kanal, aufseiten der Kathoden) zum Einsatz. Aufgrund der Komplexität reicht es als Handskizze: <gallery> anykeyx6_sch.png | Schaltplan - unbekannter Künstler, 2020, digital </gallery> =Firmware= Die Firmware ist erstaunlich einfach, zumal ich mich nicht sonderlich bemüht habe. Die LEDs werden mit der oben beschriebenen Methode (in leddrv.c) angesteuert, wobei zusätzlich noch eine Fading-Funktion zum Einsatz kommt. Das entlastet den USB-Stack und verringert das Flackern (siehe weiter unten) Die Tasten werden (sofern die PWM nicht höhere Priorität hat) jede Millisekunde abgefragt (<code>buttons_tick()</code>) und wenn der Pegel low (Taste gedrückt) ist, ein Zähler inkrementiert. Bei High-Pegel wird der Zähler auf 0 zurückgesetzt. Ist der Zähler größer als 10, gilt die entsprechende Taste gedrückt. Alle Buttons in einem Byte können über die Methode <code>buttons_values()</code> abgefragt werden. In Sachen USB wird ein Out-Report (PC -> Device) mit Netto 16 Byte und ein In-Report mit Netto 8 Byte (Device -> PC) verwendet. Der Out-Report dient zum Setzen der LEDs und sieht wie folgt aus: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index der LED (1-6) * <span class="hb2">Rx</span>: Rot-Wert der LED (0 ... 255) * <span class="hb3">Gx</span>: Grün-Wert der LED (0 ... 255) * <span class="hb4">Bx</span>: Blau-Wert der LED (0 ... 255) * <span class="hb5">Tx</span>: Dauer für den Übergang (0 ... 255, in 5 ms-Schritten) Es können somit 3 Farben gleichzeitig geschrieben werden, Index 0 wird nicht verwendet, da es üblicherweise der Init-Wert für Arrays ist und somit nicht versehentlich die Farbe einer Taste gesetzt wird. Der In-Report ist denkbar einfach, im ersten Byte steht das Bit-Muster der aktuell gedrückten Taster: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> Der Report wird bei jeder Änderung des Zustands der Taster gesendet. Das ist in mehrerlei Hinsicht nicht ganz ideal, da zum einen der Initiale Zustand (nach Öffnen des Devices) nicht ermittelt werden kann und falls doch mal ein USB-Paket verloren geht, verpasst man Tastendrücke. Aber: es musste schnell gehen. =Mechanik= Die Mechanik ist (zumindest für mich als Neuling in Sachen Design und 3D-Druck) ein Stück aufwändiger. Einfach nur die Leiterkarte auf den Tisch zu knallen geht hier nicht, es muss nicht wie aus dem Ei gepellt aussehen, aber nicht nur aus der Kategorie "form follows function" sein. Um schnell voran zu kommen, kam das MS Paint im 3D-Design zum Einsatz: SketchUp. Mit allen Einschränkungen und fehlender Parametrisierung bin ich darin leider noch immer am schnellsten, etwas für den Druck vorzubereiten. ==Tasten== Mit ein bisschen Zeichnen in 2D-Software stellte sich heraus, dass rechteckige Tasten mit 15 mm Breite und Höhe, einer Abrundung mit Radius 2,5 mm und einem Abstand von 5 mm zueinander eine angenehme Haptik aufweisen. Ein erstes Muster mit Kragen (damit die Taste nicht durchs Gehäuse fällt) aus transparentem PLA, (wenn ich mich richtig erinnere) 50 % Infill und konzentrischem Top/Bottom-Pattern (in Cura gesliced) ist schnell gedruckt und sieht, nachdem es mit Farbe beschmiert wurde um zu sehen wie dicht der Druck ist, auch nach dem Reinigen versaut aus. Licht geht durch, sieht aber eher bescheiden aus: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Ausleuchtung bei konzentrischem Druck </gallery> Als nächstes kommt die Frage: wie die LEDs und Taster montieren? um das mechanische Design zu vereinfachen, habe ich die Idee verfolgt, möglichst Gleichteile zu verwenden. In meinen letzten Leiterkarten-Bestellungen habe ich im Waste immer 1x1 mm Kupferflächen im 1,27 mm-Raster platziert, ein Streifen damit ist etwa 9,6 mm breit (bei 1,6 mm Materialdicke) - eine gute Größe für diese Anwendung. LED auf die eine Seite, Taster auf die andere und eine Idee, für die mich die Mechaniker in der Arbeit (völlig zu Recht) vermutlich nicht mehr anschauen würden: Constraining auf zwei Bezugsebenen. Normalerweise strebt man an, dass sich die Toleranzen von einer Seite aus ausbreiten, damit man die Toleranzketten in Griff halten kann. Würde hier heißen: Die Tasten sind auf die Gehäusefront referenziert und dementsprechend müssen die Taster auch an einer Ebene montiert werden, deren Toleranz sich auf die Front bezieht. Bei mir sollen die Taster aber gegen die Bodenplatte drücken. Mit vielen Nachteilen. Da es sich aktuell allerdings um ein Einzelstück handelt: Egal. Das Platinchen mit LED vorne und Taster hinten wird einfach in eine Nut im Taster eingeschoben. Bis auf einen kleinen (reproduzierbaren) Druckfehler funktioniert das prächtig. Hier die verschiedenen Designiterationen: <gallery> anykeyx6_taste_iterationen.jpg | Iterationen der Tasten 1 bis 5.5 anykeyx6_sketchup_taste_seite.png | Finales Modell der Tasten von der Seite anykeyx6_sketchup_taster_unten.png | und von unten anykeyx6_taste_einzelteile.jpg | Einzelteile der Tasten (der Taster fehlt) anykeyx6_taste_LED.jpg | Leiterkarte in die Taste eingeschoben </gallery> Mit Infill auf 100 % und der Tasterfront auf dem Druckbett entsteht eine relativ schöne Oberfläche. Da Concentric Top/Bottom-Pattern ein Kreuz in der Diagonale erzeugt hat, bin ich auf "Lines" umgestiegen, das die Taster, gemeinsam mit dem konzentrischen Rahmen fast schon "wie gekauft" aussehen lässt. Um eine bessere Farbmischung zu erzeugen (und die Taster eine eigenwillige Streuwirkung haben), habe ich etwas Band aus meinem Beschriftungsgerät (Wenn es wichtig ist: Brother P-touch) hinter den Taster geklebt. Dadurch wird die Ausleuchtung der drei LED-Kristalle zumindest ein bisschen homogener: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Zum Vergleich nochmal das Bild von oben (konzentrischer Druck) anykeyx6_beleuchtung_diffusor.jpg | links ohne Folie, rechts mit </gallery> Insgesamt hat das Sandwich eine Höhe von 12,4 mm - 0,25 mm weniger, wenn der Taster gedrückt ist. Der Kragen ist 2,5 mm nach innen versetzt. Das, plus die Dicke der Gehäuseteile, wird die Gesamtdicke des Geräts. =Gehäuse= Mit den Maßen der Tasten geht es los, wobei die Ausschnitte für diese um 0,25 mm in alle Richtungen erweitert wurden. Das bringt zwar etwas Spiel, aber bevor der Cutter angesetzt oder nochmals gedruckt werden muss, dürfen die Tasten eher ein bisschen wackeln - zumal es bei den ersten Tastern ordentlich Elefantenfüße gab. Mit einem Überstand von 7,5 mm von der Kante der Taster zu den Gehäusewänden in drei Richtungen und etwas mehr (17,5 mm) in die vierte Richtung - irgendwo muss ja die Elektronik hin - ist das Gehäuse relativ kompakt. Im inneren befinden sich zwischen den Tastern 4 mm hohe Wände - nicht zum Ausrichten, sondern vielmehr um Streulicht zwischen den Tastern zu vermeiden. Damit sich das Gehäuse nicht durchbiegt und dadurch versehentlich mehrere Taster auf einmal betätigt werden, befinden sich in den Kreuzungspunkten der Taster Erhöhungen, die die Stabilität in Z-Richtung erhöhen. Um Material und vor allem Druckzeit zu sparen, gab es zwei abgeschnittene Druckmuster, die man dank transparentem Filament auf weißem Grund fast nicht sieht: <gallery> anykeyx6_druckmuster_deckel.jpg | Druckmuster für die Aufnahme der Tasten </gallery> Als Zugentlastung des fest installierten USB-Kabels befindet sich hinter dem U-förmigen Ausschnitt eine kleine Rampe und ein Loch, durch den ein Kabelbinder passt. Die Rampe dient lediglich dazu, dass der Kabelbinder die untere Gehäusehälfte nicht nach unten drückt. Man könnte mutmaßen, dass durch die Druckschichten bedingte Treppenstruktur die Leitung sogar ein bisschen verhakt wird. 3 Löcher, durch die M2,5-Schrauben passen, dienen zur Befestigung der Bodenplatte. Insgesamt gab es 4 Iterationen, wobei nur zwei den Weg auf den Drucker gefunden haben - und das auch nur, weil sich das erste Druckteil vom Druckbett abgelöst und dadurch unschön verzogen hat. Anscheinend sind die STL-Daten nicht ganz sauber, wodurch das Modell wohl etwas in der Luft hängt. Durch einen Microstep von -0,001 in Z-Richtung wurde das Druckergebnis besser, aber die erste Lage ist trotzdem noch etwas lückig... <gallery> anykeyx6_sketchup_deckel.png | 3D-Modell des Deckels anykeyx6_deckel_vergurkt.jpg | Der erste Versuch (vergurkt) anykeyx6_Deckel.jpg | Der bessere Druck. </gallery> Das untere Gehäuseteil sind eigentlich 7 Teile und brauchte keine Revision (aber einen kleinen Eingriff mit dem Skalpell). Die Komplexität ist auch deutlich geringer. Auffallend sind zunächst die 4 "Kamine" - die Idee dahinter ist, Muttern einzulegen und diese mit dem oberen Gehäuseteil zu verschrauben. Das ganze ist (eher unbeabsichtigt) auf Pressung designed, sowohl für die Mutter, als auch in Richtung anderes Gehäuseteil. Immerhin rutscht nichts. An den Positionen der Taster befinden sich Sacklöcher/Kerben - aus einem sehr einfachen Grund: Material und Druckzeit sparen. Die Bodenplatte soll in weiten Teilen dick genug sein, dass sie stabil ist aber auf keinen Fall ein zweites Mal gedruckt werden muss. Um die Taster in der Höhe einzupassen, werden kleine Distanznippel eingesetzt, die klein sind und dadurch sehr schnell angepasst und gedruckt werden können. Weil ich keinen Sekundenkleber mehr da hatte, sind sie lediglich einseitig auf der Bodenplatte mit doppelseitigem Klebeband befestigt. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D-Modell der Bodenplatte anykeyx6_shim.png | Das 3D-Modell eines Nippel anykeyx6_bodenplatte_benippelt.jpg | Bodenplatte mit Muttern und Nippeln </gallery> Insgesamt war der Drucker etwa 4 Stunden beschäftigt, wobei er auch nicht mit maximaler Geschwindigkeit lief. Die Materialkosten liegen (ohne Probestücke und Fehldrucke) bei etwa 50 cent wenn ich mich nicht täusche, also nicht wirklich der Rede wert. =Zusammenbau= Ursprünglich habe ich einen Atmega8 im DIP-Gehäuse vorgesehen. Da es aber doch ein bisschen eng geworden wäre, kam dann doch einer im TQFP-Gehäuse zum Einsatz. Neben dem Mikrocontroller finden auch die 9 Transistoren für die LED-Ansteuerung Platz auf der Selfmade-Punktrasterplatine: <gallery> anykeyx6_platine.jpg | Bestückte Leiterkarte. </gallery> Die LED-Tasten bekommen gehörig lange Anschlussleitungen aus Kupferlackdraht, die durchgepiepst und auf passend beschriftete Klebebandstreifen landen. Miteinander verdrillt und verlötet kommen sie dann an die FETs. Gleiches Spiel für die Massen der Taster. <gallery> anykeyx6_tastenverdrahtung.jpg | Etwas Ordnung im Chaos </gallery> Damit die Tasten beim Zusammenfügen nicht immer wieder aus ihren Löchern entwischen, kommt Klebeband von außen auf das Gehäuse. Zur Sicherheit mit Nummern beschriftet, damit mit Drehen und Spiegeln nix schief geht. Tasten eingelegt, Leitungen im Gehäuse verlegt und den Kupfer-Knäuel zusammengedrückt. Papa sagte schon immer: Salat ist gesund. Das USB-Kabel liegt fest verzurrt und sehr engem Biegeradius im Gehäuse - hält (hoffentlich). <gallery> anykeyx6_boden_und_deckel.jpg | Beide Gehäusehälften anykeyx6_deckel_verklebt.jpg | Bestückungshilfe anykeyx6_deckel_assy.jpg | Deckel mit eingelegten Komponenten </gallery> In die untere Gehäusehälfte sind die Nippel schon eingeklebt und es wird spannend: passt es? Leider sind keine Senkkopfschrauben im Haus, also bleibt es mit den verzinkten Zylinderkopf-Schrauben etwas hässlich. Oder pragmatisch. Naja, es hält - und die Tasten liegen so im Gehäuse, dass sie weder (allzu sehr) klappern noch permanent gedrückt werden. Erfolg! :) Um bei den Tasten nicht im kompletten Blindflug zu sein, ziert noch ein Label und ein paar Symbole der FontAwesome die obere Reihe. Damit sollte nun nichts mehr schief geben. =Software= ==Erster Test== Die erste Testsoftware ist in Python geschrieben und lässt einen Regenbogen durchlaufen. Der Einfachheit halber fasst sie nur eine LED gleichzeitig an: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> Sieht dann als Momentaufnahme in etwa wie folgt aus: <gallery> anykeyx6_rgb_demo.jpg | Farben, yay! </gallery> ==Der OBS-Client== Ein "echtes" Plugin für OSB Studio zu schreiben spare ich mir mangels Tiefe in C++. Stattdessen nutze ich [https://github.com/Palakis/obs-websocket obs-websocket], das eine API für C# anbietet, die extrem einfach zu bedienen ist. Für die Buttons ist eine extrem rudimentäre Klasse sehr schnell zusammengehackt. Gänzlich ohne Fehlerbehandlung. Das Auslesen der Buttons erfolgt in einem Background-Worker, der Events feuert (und beim Loslassen zusätzlich die Dauer des Drückens ermittelt), das Setzen der LED-Farben erfolgt für alle 6. Hier merkt man auch wie heiß die Nadel ist mit der gestrickt wird: Zwischen dem Schreiben der beiden "Sets" legt sich die Software für eine Millisekunde schlafen. Der Grund einst einfach die dämlich - schreibt man zu schnell, geht evtl. das erste der beiden Datenpakete in der Firmware verloren, weil die Übergabe nicht (wenn man es so nennen will) threadsafe ist. Die GUI hat lediglich einen "Connect"-Button, der nur gedrückt werden sollte, wenn OBS läuft und die Hardware verbunden ist. Die Konfiguration ist ebenfalls eher grundlegend und in AnykeyOBS.exe.config zu finden. Hier kann für jede Taste die Aktiv/Inaktiv-Farbe als Hex-Code (oder named color, ungetestet) abgelegt werden, die Funktion definiert und ein Argument für diese Funktion angegeben werden. Zum Zuordnen einer Szene packt man in die Funktion "Scene" und schreibt den zugehörigen Szenen-Namen ins Argument. Für die Aufnahme heißt die Funktion "Record" und als Argument kann "Toggle", "Start" und "Stop" definiert werden. Streaming wird noch nicht unterstützt. Aus mir nicht ganz verständlichen Gründen kann der Zustand des Streamings/Recordings nur über Events ermittelt werden, dadurch bleibt die Taste mit entsprechender Zuordnung beim Start des Programms orange. Dies ist auch die (fest hinterlegte) Farbe für Übergänge zwischen Aufnahme und keine Aufnahme. Ein weiteres Feature ist das Abbrechen einer Funktion - Grundsätzlich werden die Aktionen erst beim Loslassen des Tasters getriggert - außer man drückt diesen länger als eine Sekunde. In diesem Fall wird die Aktion abgebrochen. Insgesamt kann man die Software allerhöchstens als Proof of Concept bezeichnen. Es funktioniert, irgendwie. ===Feuerprobe=== Mittlerweile durfte ich meine Schwester sogar besuchen, um ihr die Hardware zu geben. yay! Das Einrichten fand aber trotzdem online statt. obs-websockt installiert, AnykeyOBS aufs Tablet und: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Mist. Die vermutliche Ursache ist schnell gefunden: Bei manchen USB-Geräten kann der Name nicht gelesen werden. Eine Packung try-catch auf das Problem geworfen und eine Prise <code>Console.WriteLine</code>s und das Programm bleib nach dem Klick auf "Connect" geöffnet. "Leuchten die Knöppe?" - "Oh mann, wie geil" - "Also ja?". Danach hörte ich nur noch wildes Klicken. Ich glaube, das Teil gefällt. Und so sieht es aus: [[Datei:anykeyx6_demo.mp4]] =Fazit= Wo fange ich an? Beim Guten, beim Schlechten oder bei den Sachen, für die ich mich schäme? Unterm Strich: für eine sehr hemdsärmelig zusammengestrickte Hardware sieht es (ohne dass ich mich selbst loben möchte) ganz ordentlich aus. Schlimm wird es erst, wenn man unter die Haube schaut. Das dafür aber auch konsequent. Das Gute: * Meine Schwester hat etwas, das ihr hoffentlich die Arbeit etwas erleichtert * Ich habe wieder einiges in Sachen 3D-Druck gelernt * Es hat ziemlich viel Spaß gemacht * Alles ist bunt Das Schlechte: * Decoupling, welches Decoupling? * LEDs ** Nicht sonderlich hell ** Flackern bei USB-Traffic (durch INT0) ** In dunkler Umgebung zu hell und bei Tageslicht schlecht sichtbar * Das Setzen von LEDs und Tastendrücke können verschluckt werden * Taster ** Können auch von der Gehäuseunterseite betätigt werden ** Relativ laut (im Video hörbar) ** Wackeln, sind schief und haben keine Führung * Software ** An allen Ecken und Enden rudimentär, wenn etwas ausfällt, funktioniert erst einmal nichts ** Kein automatisches Verbinden mit OBS und der Hardware ** Keine GUI für die Konfiguration ** So gut wie keine Funktionen in OBS unterstützt ** Außer OBS-Steuerung keine weiteren Funktionen * Keine Standby-States =Downloads= * [[Datei:Anykeyx6.zip]] SketchUp-Dateien, zugehörige STLs, Firmware und C#-Software um mit OBS zu sprechen. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] f65b4bc5553d77904eff831fb1f8aa93e0fb802c 1588 1587 2020-05-11T18:23:11Z Chris 2 . wikitext text/x-wiki ''There's also an [[Anykey_x6/en|English translation]] of this article.'' [[Datei:anykeyx6_komplett.jpg|thumb|Fertig aufgebaute Hardware (Farben leicht retuschiert)]] Meine Schwester ist Lehrerin. Ein Job, um den ich sie nicht beneide - gerade in 2020. Hier in Bayern fängt (Stand Anfang Mai) das Leben an der Schule langsam wieder an, parallel zum Unterricht in den Schulen müssen jedoch die daheim bleibenden Kinder noch unterrichtet werden. Wenn man die eigene Arbeit ernst nimmt, ist das kein Spaß. Klar, man könnte für das Eigenstudium einfach Arbeitsblätter über den Zaun werfen und auf Seiten in den Büchern verweisen, aber wenn ich da an meine eigene Schulzeit und die eher extrinsische Motivation denke... Obwohl meine Schwester schon sehr viel digital hat, braucht Unterricht (gerade bei Sprachen) auch jemanden, der/die vor der Klasse spricht und natürlich ist eigenständiges Lernen für viele nicht ganz einfach. Aus diesem Grund hat meine Schwester angefangen, Videos zu machen. Vorerst nur mit ausgedruckten Blättern und dem Handy auf dem Stativ. Um Ihre digitalen Materialien besser nutzen zu können, fragte sie dann doch mal nach einem screen recorder. [https://obsproject.com/ OBS] war schnell installiert und eingerichtet. Blöd nur, dass sie keinen zweiten Monitor (bzw. Displayport-Adapter) für ihr MS Surface hat. Damit ihre Schüler sie auch mal sehen können (oder auch mal "Tafelunterricht" zu machen), habe ich ihr mehrere Szenen in OBS eingerichtet: * Bildschirmaufnahme * Bildschirmaufnahme + Kamera in der Ecke * Kamera Blöd ist nur, dass sie ohne besagten zweiten Bildschirm für jede Aktion OBS in den Vordergrund holen muss. Zwar kann man dort auch globale Hotkeys anlegen, aber ohne vollständige Tastatur läuft man sehr schnell Gefahr, Doppelbelegungen zu bekommen und dadurch sehr merkwürdiges Verhalten am PC zu haben. Gleichzeitig sieht man nicht, was OBS nun tatsächlich macht. Ja, man kann eine Fernbedienung für OBS auf dem Tablet oder Smartphone installieren, aber das schafft eigentlich nur mehr Probleme als es löst, zumal man die (freien) Clients, die ich auf Anhieb gefunden hab für jede Session neu konfigurieren muss. Zudem muss das Gerät am Laufen halten und kann die Tasten nicht erfühlen. Das lenkt unnötig ab und erhöht auch die Akzeptanz nicht wirklich. Auch fertige Lösungen wie das Elgato Stream Deck ist für die (hoffentlich) kurze Nutzungsdauer unverhältnismäßig teuer. Gleichzeitig sitzt hier ein Ingenieur herum, der aufgrund der aktuellen Situation erst einmal Gleitzeit abbaut. =Die Idee= Da kann man doch was basteln. Ein paar Taster, ein paar LEDs, ein bisschen Firmware und noch ein paar Zeilen Code auf dem PC. Was soll daran so aufwändig sein? Um eines vorweg zu nehmen: Übers Ziel hinausschießen, das kann daran aufwändig werden. Ziel ist, 6-8 bunt beleuchtete Taster zu haben, die in OBS eingebunden werden können. Der Mikrocontroller ist schnell gefunden. Um nicht zu weit von den Codebeispielen von [https://www.obdev.at/products/vusb/index-de.html V-USB] zu sein, soll ein oller ATmega8 zum Einsatz kommen. Weil ich schon länger was mit intelligenten LEDs machen wollte, liegt schon viel zu lange ein Streifen mit WS2812B herum. Der Plan war, diese – womöglich sogar noch auf dem Streifen – auf Taster zu kleben. Natürlich muss der [[wpde:Woman acceptance factor|WAF]] auch halbwegs passen, deshalb ist ein nicht zu schäbiges Gehäuse angesagt. 3D-Drucker sei dank bin ich auch dazu (zumindest seitens der Ausstattung) in der Lage. =Elektronik= Die Ernüchterung kam schneller als erwartet. Dass die Ansteuerung der LEDs zeitkritisch ist, wusste ich. Dass das auch für V-USB gilt, ebenfalls. Dass man beides nicht so einfach kombinieren kann, würde dann sehr schnell klar. Der USB-Stack braucht zwingend einen Pin-Interrupt, für die Ansteuerung der LEDs muss dieser aber abgeschaltet werden – sonst blinkt alles wie ein Weihnachtsbaum auf LSD. Tim (aka cpldcpu) hat sich die Mühe gemacht, V-USB mit [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling zu ermöglichen] - gleichzeitig sogar mit entsprechender LED. Den Weg wollte ich nicht gehen, weil das potenziell an anderen Stellen schmerzhaft werden könnte. Ok, was nun? Ein Coprozessor, der UART/I²C auf das LED-Protokoll umwandelt? Eigentlich wollte ich kein Mehrprozessor-System bauen – und auch hier bleibt das Problem mit Interrupts vs. keine Interrupts, auch durch die Einschränkungen durch USI dürfte das noch etwas unentspannter sein. Da ist guter Rat teuer. Auf einfarbige LEDs wollte ich aber auch nicht zurückgehen. ==LED-Treiber== 6 RGB-LEDs mit PWM anzusteuern, braucht es 18 PWM-Kanäle. Das hat glaube ich kein AVR8. ich habe zwar noch einen PCA9685 herumliegen, der aber auch nur 16 Kanäle bereitstellt. Zudem nimmt das Teil mit seinem Breakout-Board relativ viel Platz ein. Zu viel für das, was ich vor dem inneren Auge habe. Habe ich 18 Kanäle geschrieben? Jein. Betreibt man Multiplexing, reichen zwischen 3 und 6. Schlussendlich habe ich mich dafür entschieden, die Farben in den Multiplex zu nehmen und den PWM pro Taste laufen zu lassen - mit entsprechenden Einbußen der Helligkeit (ein Drittel). Aber wo bekommt man an einem ATmega8 6 synchrone PWM-Kanäle her? Ganz einfach: gar nicht. Zumindest in Hardware - anders schaut es in Software aus, wo es auch keine richtige PWM ist, sondern eher eine Pulsleistungsmodulation (kurz PDM - einen passenden Begriff konnte ich finden, daher die Neukreation), wie sie 2011 auf der [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite] schon beschrieben wurde. Um es kurz zu beschreiben: bei gewöhnlicher PWM gibt es für jeden Kanal zwei Schaltzeitpunkte, von denen einer pro Kanal individuell ist (da er den Helligkeitswert vorgibt). Hat man n Kanäle, gibt es n Zeitpunkte, die man möglichst zielgenau treffen muss. Gerade wenn diese nah beieinander liegen, kann das zu Timingproblemen führen. Der hier verwendete Dimmer funktioniert anders. Man muss dabei bedenken, dass es beim Dimmen von LEDs relativ egal ist, ob sie über einen Zyklus am Stück an sind, oder ob sie zwischendurch ausgeschaltet werden - wichtig ist unterm Strich nur, wie viel sie im im Laufe eines Zyklus aktiv sind. Bei einer Auflösung von b bit gibt es bei dieser Methode b Zeitpunkte - ganz egal wie viele Kanäle man verwendet und: deren Timing ist fest. Zudem sind diese sind zeitlich immer mit Faktor 2 voneinander getrennt. Nun schaltet man den Kanal immer dann an, wenn im Helligkeitswert das "Bit" des zugehörigen Zeitschlitzes aktiv ist. Da es visuell deutlich besser als mit Text funktioniert, hier mal zwei Beispiele mit einer Modulation mit 3 Bit. Die Wertigkeit steht links, die An-Zeiten entsprechen den grünen Blöcken (deren X-Achse der Zeit entspricht) und die nötigen Interrupts sind mit roten Pfeilen markiert: <gallery> anykeyx6_pwm.png | Pulsweitenmodulation anykeyx6_plm.png | Pulsleistungsmodulation </gallery> Betrachtet man die aktive Fläche der einzelnen Helligkeitswerte, kommt man auf das gleiche - nur dass die PDM deutlich ressourcenschonender ist. Dazu kommt der Effekt, dass durch das "Zerhacken" der PWM die LEDs mit einer höheren Frequenz flackern (auch wenn sie variiert). Dadurch wird der Stroboskop-Effekt verringert - des einen Freud ist des anderen Leid: achtet man auf EMV, wird es and er Stelle unangenehmer. Aber genug dazu. Aufgrund des Multiplexing gibt es, wie oben beschrieben, nur ein Drittel an Helligkeit. Die meisten LEDs halten bei pulsförmiger Ansteuerung deutlich mehr Strom als im Dauerbetrieb aus weil der limitierende Faktor die Erwärmung ist. Da die LEDs (im 5050-Gehäuse) für den Aufbau von einem LED-Streifen "geerntet" wurden, habe ich kein Datenblatt zur Komponente, aber Wissen: z. B. kommt für den roten Strang ein 330 Ohm-Widerstand zum Einsatz, bei 12 V und 3 roten LEDs in Reihe mit ca. 1,85 V Vorwärtsspannung sind das etwa 20 mA. Ohne weitere Infos zu maximalen Strömen und weil die Helligkeit eigentlich reichen sollte, bin ich bei diesem Strom geblieben. ==Taster== Die Taster kommen direkt an IOs und sind gegen Masse verschaltet. Eine rudimentäre Entprellung wird in Software gemacht. ==USB== Die USB-Beschaltung entspricht weitestgehend der aus den Beispielen von Objective Development. Aus reiner Faulheit habe ich die Schutzbeschaltung vom [[USB-Fußtaster]] übernommen. Sprichwörtlich: Die nötigen Bauteile bestückt und die Leiterkarte auf die passende Größe gestutzt. ==Schaltplan== Die gesamte Schaltung ist also relativ einfach. Als FETs für die LEDs kommen BSS84 (p-Kanal, aufseiten der Anoden) und BSS138 (n-Kanal, aufseiten der Kathoden) zum Einsatz. Aufgrund der Komplexität reicht es als Handskizze: <gallery> anykeyx6_sch.png | Schaltplan - unbekannter Künstler, 2020, digital </gallery> =Firmware= Die Firmware ist erstaunlich einfach, zumal ich mich nicht sonderlich bemüht habe. Die LEDs werden mit der oben beschriebenen Methode (in leddrv.c) angesteuert, wobei zusätzlich noch eine Fading-Funktion zum Einsatz kommt. Das entlastet den USB-Stack und verringert das Flackern (siehe weiter unten) Die Tasten werden (sofern die PWM nicht höhere Priorität hat) jede Millisekunde abgefragt (<code>buttons_tick()</code>) und wenn der Pegel low (Taste gedrückt) ist, ein Zähler inkrementiert. Bei High-Pegel wird der Zähler auf 0 zurückgesetzt. Ist der Zähler größer als 10, gilt die entsprechende Taste gedrückt. Alle Buttons in einem Byte können über die Methode <code>buttons_values()</code> abgefragt werden. In Sachen USB wird ein Out-Report (PC -> Device) mit Netto 16 Byte und ein In-Report mit Netto 8 Byte (Device -> PC) verwendet. Der Out-Report dient zum Setzen der LEDs und sieht wie folgt aus: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index der LED (1-6) * <span class="hb2">Rx</span>: Rot-Wert der LED (0 ... 255) * <span class="hb3">Gx</span>: Grün-Wert der LED (0 ... 255) * <span class="hb4">Bx</span>: Blau-Wert der LED (0 ... 255) * <span class="hb5">Tx</span>: Dauer für den Übergang (0 ... 255, in 5 ms-Schritten) Es können somit 3 Farben gleichzeitig geschrieben werden, Index 0 wird nicht verwendet, da es üblicherweise der Init-Wert für Arrays ist und somit nicht versehentlich die Farbe einer Taste gesetzt wird. Der In-Report ist denkbar einfach, im ersten Byte steht das Bit-Muster der aktuell gedrückten Taster: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> Der Report wird bei jeder Änderung des Zustands der Taster gesendet. Das ist in mehrerlei Hinsicht nicht ganz ideal, da zum einen der Initiale Zustand (nach Öffnen des Devices) nicht ermittelt werden kann und falls doch mal ein USB-Paket verloren geht, verpasst man Tastendrücke. Aber: es musste schnell gehen. =Mechanik= Die Mechanik ist (zumindest für mich als Neuling in Sachen Design und 3D-Druck) ein Stück aufwändiger. Einfach nur die Leiterkarte auf den Tisch zu knallen geht hier nicht, es muss nicht wie aus dem Ei gepellt aussehen, aber nicht nur aus der Kategorie "form follows function" sein. Um schnell voran zu kommen, kam das MS Paint im 3D-Design zum Einsatz: SketchUp. Mit allen Einschränkungen und fehlender Parametrisierung bin ich darin leider noch immer am schnellsten, etwas für den Druck vorzubereiten. ==Tasten== Mit ein bisschen Zeichnen in 2D-Software stellte sich heraus, dass rechteckige Tasten mit 15 mm Breite und Höhe, einer Abrundung mit Radius 2,5 mm und einem Abstand von 5 mm zueinander eine angenehme Haptik aufweisen. Ein erstes Muster mit Kragen (damit die Taste nicht durchs Gehäuse fällt) aus transparentem PLA, (wenn ich mich richtig erinnere) 50 % Infill und konzentrischem Top/Bottom-Pattern (in Cura gesliced) ist schnell gedruckt und sieht, nachdem es mit Farbe beschmiert wurde um zu sehen wie dicht der Druck ist, auch nach dem Reinigen versaut aus. Licht geht durch, sieht aber eher bescheiden aus: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Ausleuchtung bei konzentrischem Druck </gallery> Als nächstes kommt die Frage: wie die LEDs und Taster montieren? um das mechanische Design zu vereinfachen, habe ich die Idee verfolgt, möglichst Gleichteile zu verwenden. In meinen letzten Leiterkarten-Bestellungen habe ich im Waste immer 1x1 mm Kupferflächen im 1,27 mm-Raster platziert, ein Streifen damit ist etwa 9,6 mm breit (bei 1,6 mm Materialdicke) - eine gute Größe für diese Anwendung. LED auf die eine Seite, Taster auf die andere und eine Idee, für die mich die Mechaniker in der Arbeit (völlig zu Recht) vermutlich nicht mehr anschauen würden: Constraining auf zwei Bezugsebenen. Normalerweise strebt man an, dass sich die Toleranzen von einer Seite aus ausbreiten, damit man die Toleranzketten in Griff halten kann. Würde hier heißen: Die Tasten sind auf die Gehäusefront referenziert und dementsprechend müssen die Taster auch an einer Ebene montiert werden, deren Toleranz sich auf die Front bezieht. Bei mir sollen die Taster aber gegen die Bodenplatte drücken. Mit vielen Nachteilen. Da es sich aktuell allerdings um ein Einzelstück handelt: Egal. Das Platinchen mit LED vorne und Taster hinten wird einfach in eine Nut im Taster eingeschoben. Bis auf einen kleinen (reproduzierbaren) Druckfehler funktioniert das prächtig. Hier die verschiedenen Designiterationen: <gallery> anykeyx6_taste_iterationen.jpg | Iterationen der Tasten 1 bis 5.5 anykeyx6_sketchup_taste_seite.png | Finales Modell der Tasten von der Seite anykeyx6_sketchup_taster_unten.png | und von unten anykeyx6_taste_einzelteile.jpg | Einzelteile der Tasten (der Taster fehlt) anykeyx6_taste_LED.jpg | Leiterkarte in die Taste eingeschoben </gallery> Mit Infill auf 100 % und der Tasterfront auf dem Druckbett entsteht eine relativ schöne Oberfläche. Da Concentric Top/Bottom-Pattern ein Kreuz in der Diagonale erzeugt hat, bin ich auf "Lines" umgestiegen, das die Taster, gemeinsam mit dem konzentrischen Rahmen fast schon "wie gekauft" aussehen lässt. Um eine bessere Farbmischung zu erzeugen (und die Taster eine eigenwillige Streuwirkung haben), habe ich etwas Band aus meinem Beschriftungsgerät (Wenn es wichtig ist: Brother P-touch) hinter den Taster geklebt. Dadurch wird die Ausleuchtung der drei LED-Kristalle zumindest ein bisschen homogener: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Zum Vergleich nochmal das Bild von oben (konzentrischer Druck) anykeyx6_beleuchtung_diffusor.jpg | links ohne Folie, rechts mit </gallery> Insgesamt hat das Sandwich eine Höhe von 12,4 mm - 0,25 mm weniger, wenn der Taster gedrückt ist. Der Kragen ist 2,5 mm nach innen versetzt. Das, plus die Dicke der Gehäuseteile, wird die Gesamtdicke des Geräts. =Gehäuse= Mit den Maßen der Tasten geht es los, wobei die Ausschnitte für diese um 0,25 mm in alle Richtungen erweitert wurden. Das bringt zwar etwas Spiel, aber bevor der Cutter angesetzt oder nochmals gedruckt werden muss, dürfen die Tasten eher ein bisschen wackeln - zumal es bei den ersten Tastern ordentlich Elefantenfüße gab. Mit einem Überstand von 7,5 mm von der Kante der Taster zu den Gehäusewänden in drei Richtungen und etwas mehr (17,5 mm) in die vierte Richtung - irgendwo muss ja die Elektronik hin - ist das Gehäuse relativ kompakt. Im inneren befinden sich zwischen den Tastern 4 mm hohe Wände - nicht zum Ausrichten, sondern vielmehr um Streulicht zwischen den Tastern zu vermeiden. Damit sich das Gehäuse nicht durchbiegt und dadurch versehentlich mehrere Taster auf einmal betätigt werden, befinden sich in den Kreuzungspunkten der Taster Erhöhungen, die die Stabilität in Z-Richtung erhöhen. Um Material und vor allem Druckzeit zu sparen, gab es zwei abgeschnittene Druckmuster, die man dank transparentem Filament auf weißem Grund fast nicht sieht: <gallery> anykeyx6_druckmuster_deckel.jpg | Druckmuster für die Aufnahme der Tasten </gallery> Als Zugentlastung des fest installierten USB-Kabels befindet sich hinter dem U-förmigen Ausschnitt eine kleine Rampe und ein Loch, durch den ein Kabelbinder passt. Die Rampe dient lediglich dazu, dass der Kabelbinder die untere Gehäusehälfte nicht nach unten drückt. Man könnte mutmaßen, dass durch die Druckschichten bedingte Treppenstruktur die Leitung sogar ein bisschen verhakt wird. 3 Löcher, durch die M2,5-Schrauben passen, dienen zur Befestigung der Bodenplatte. Insgesamt gab es 4 Iterationen, wobei nur zwei den Weg auf den Drucker gefunden haben - und das auch nur, weil sich das erste Druckteil vom Druckbett abgelöst und dadurch unschön verzogen hat. Anscheinend sind die STL-Daten nicht ganz sauber, wodurch das Modell wohl etwas in der Luft hängt. Durch einen Microstep von -0,001 in Z-Richtung wurde das Druckergebnis besser, aber die erste Lage ist trotzdem noch etwas lückig... <gallery> anykeyx6_sketchup_deckel.png | 3D-Modell des Deckels anykeyx6_deckel_vergurkt.jpg | Der erste Versuch (vergurkt) anykeyx6_Deckel.jpg | Der bessere Druck. </gallery> Das untere Gehäuseteil sind eigentlich 7 Teile und brauchte keine Revision (aber einen kleinen Eingriff mit dem Skalpell). Die Komplexität ist auch deutlich geringer. Auffallend sind zunächst die 4 "Kamine" - die Idee dahinter ist, Muttern einzulegen und diese mit dem oberen Gehäuseteil zu verschrauben. Das ganze ist (eher unbeabsichtigt) auf Pressung designed, sowohl für die Mutter, als auch in Richtung anderes Gehäuseteil. Immerhin rutscht nichts. An den Positionen der Taster befinden sich Sacklöcher/Kerben - aus einem sehr einfachen Grund: Material und Druckzeit sparen. Die Bodenplatte soll in weiten Teilen dick genug sein, dass sie stabil ist aber auf keinen Fall ein zweites Mal gedruckt werden muss. Um die Taster in der Höhe einzupassen, werden kleine Distanznippel eingesetzt, die klein sind und dadurch sehr schnell angepasst und gedruckt werden können. Weil ich keinen Sekundenkleber mehr da hatte, sind sie lediglich einseitig auf der Bodenplatte mit doppelseitigem Klebeband befestigt. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D-Modell der Bodenplatte anykeyx6_shim.png | Das 3D-Modell eines Nippel anykeyx6_bodenplatte_benippelt.jpg | Bodenplatte mit Muttern und Nippeln </gallery> Insgesamt war der Drucker etwa 4 Stunden beschäftigt, wobei er auch nicht mit maximaler Geschwindigkeit lief. Die Materialkosten liegen (ohne Probestücke und Fehldrucke) bei etwa 50 cent wenn ich mich nicht täusche, also nicht wirklich der Rede wert. =Zusammenbau= Ursprünglich habe ich einen Atmega8 im DIP-Gehäuse vorgesehen. Da es aber doch ein bisschen eng geworden wäre, kam dann doch einer im TQFP-Gehäuse zum Einsatz. Neben dem Mikrocontroller finden auch die 9 Transistoren für die LED-Ansteuerung Platz auf der Selfmade-Punktrasterplatine: <gallery> anykeyx6_platine.jpg | Bestückte Leiterkarte. </gallery> Die LED-Tasten bekommen gehörig lange Anschlussleitungen aus Kupferlackdraht, die durchgepiepst und auf passend beschriftete Klebebandstreifen landen. Miteinander verdrillt und verlötet kommen sie dann an die FETs. Gleiches Spiel für die Massen der Taster. <gallery> anykeyx6_tastenverdrahtung.jpg | Etwas Ordnung im Chaos </gallery> Damit die Tasten beim Zusammenfügen nicht immer wieder aus ihren Löchern entwischen, kommt Klebeband von außen auf das Gehäuse. Zur Sicherheit mit Nummern beschriftet, damit mit Drehen und Spiegeln nix schief geht. Tasten eingelegt, Leitungen im Gehäuse verlegt und den Kupfer-Knäuel zusammengedrückt. Papa sagte schon immer: Salat ist gesund. Das USB-Kabel liegt fest verzurrt und sehr engem Biegeradius im Gehäuse - hält (hoffentlich). <gallery> anykeyx6_boden_und_deckel.jpg | Beide Gehäusehälften anykeyx6_deckel_verklebt.jpg | Bestückungshilfe anykeyx6_deckel_assy.jpg | Deckel mit eingelegten Komponenten </gallery> In die untere Gehäusehälfte sind die Nippel schon eingeklebt und es wird spannend: passt es? Leider sind keine Senkkopfschrauben im Haus, also bleibt es mit den verzinkten Zylinderkopf-Schrauben etwas hässlich. Oder pragmatisch. Naja, es hält - und die Tasten liegen so im Gehäuse, dass sie weder (allzu sehr) klappern noch permanent gedrückt werden. Erfolg! :) Um bei den Tasten nicht im kompletten Blindflug zu sein, ziert noch ein Label und ein paar Symbole der FontAwesome die obere Reihe. Damit sollte nun nichts mehr schief geben. =Software= ==Erster Test== Die erste Testsoftware ist in Python geschrieben und lässt einen Regenbogen durchlaufen. Der Einfachheit halber fasst sie nur eine LED gleichzeitig an: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> Sieht dann als Momentaufnahme in etwa wie folgt aus: <gallery> anykeyx6_rgb_demo.jpg | Farben, yay! </gallery> ==Der OBS-Client== Ein "echtes" Plugin für OSB Studio zu schreiben spare ich mir mangels Tiefe in C++. Stattdessen nutze ich [https://github.com/Palakis/obs-websocket obs-websocket], das eine API für C# anbietet, die extrem einfach zu bedienen ist. Für die Buttons ist eine extrem rudimentäre Klasse sehr schnell zusammengehackt. Gänzlich ohne Fehlerbehandlung. Das Auslesen der Buttons erfolgt in einem Background-Worker, der Events feuert (und beim Loslassen zusätzlich die Dauer des Drückens ermittelt), das Setzen der LED-Farben erfolgt für alle 6. Hier merkt man auch wie heiß die Nadel ist mit der gestrickt wird: Zwischen dem Schreiben der beiden "Sets" legt sich die Software für eine Millisekunde schlafen. Der Grund einst einfach die dämlich - schreibt man zu schnell, geht evtl. das erste der beiden Datenpakete in der Firmware verloren, weil die Übergabe nicht (wenn man es so nennen will) threadsafe ist. Die GUI hat lediglich einen "Connect"-Button, der nur gedrückt werden sollte, wenn OBS läuft und die Hardware verbunden ist. Die Konfiguration ist ebenfalls eher grundlegend und in AnykeyOBS.exe.config zu finden. Hier kann für jede Taste die Aktiv/Inaktiv-Farbe als Hex-Code (oder named color, ungetestet) abgelegt werden, die Funktion definiert und ein Argument für diese Funktion angegeben werden. Zum Zuordnen einer Szene packt man in die Funktion "Scene" und schreibt den zugehörigen Szenen-Namen ins Argument. Für die Aufnahme heißt die Funktion "Record" und als Argument kann "Toggle", "Start" und "Stop" definiert werden. Streaming wird noch nicht unterstützt. Aus mir nicht ganz verständlichen Gründen kann der Zustand des Streamings/Recordings nur über Events ermittelt werden, dadurch bleibt die Taste mit entsprechender Zuordnung beim Start des Programms orange. Dies ist auch die (fest hinterlegte) Farbe für Übergänge zwischen Aufnahme und keine Aufnahme. Ein weiteres Feature ist das Abbrechen einer Funktion - Grundsätzlich werden die Aktionen erst beim Loslassen des Tasters getriggert - außer man drückt diesen länger als eine Sekunde. In diesem Fall wird die Aktion abgebrochen. Insgesamt kann man die Software allerhöchstens als Proof of Concept bezeichnen. Es funktioniert, irgendwie. ===Feuerprobe=== Mittlerweile durfte ich meine Schwester sogar besuchen, um ihr die Hardware zu geben. yay! Das Einrichten fand aber trotzdem online statt. obs-websockt installiert, AnykeyOBS aufs Tablet und: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Mist. Die vermutliche Ursache ist schnell gefunden: Bei manchen USB-Geräten kann der Name nicht gelesen werden. Eine Packung try-catch auf das Problem geworfen und eine Prise <code>Console.WriteLine</code>s und das Programm bleib nach dem Klick auf "Connect" geöffnet. "Leuchten die Knöppe?" - "Oh mann, wie geil" - "Also ja?". Danach hörte ich nur noch wildes Klicken. Ich glaube, das Teil gefällt. Und so sieht es aus: [[Datei:anykeyx6_demo.mp4]] =Fazit= Wo fange ich an? Beim Guten, beim Schlechten oder bei den Sachen, für die ich mich schäme? Unterm Strich: für eine sehr hemdsärmelig zusammengestrickte Hardware sieht es (ohne dass ich mich selbst loben möchte) ganz ordentlich aus. Schlimm wird es erst, wenn man unter die Haube schaut. Das dafür aber auch konsequent. Das Gute: * Meine Schwester hat etwas, das ihr hoffentlich die Arbeit etwas erleichtert * Ich habe wieder einiges in Sachen 3D-Druck gelernt * Es hat ziemlich viel Spaß gemacht * Alles ist bunt Das Schlechte: * Decoupling, welches Decoupling? * LEDs ** Nicht sonderlich hell ** Flackern bei USB-Traffic (durch INT0) ** In dunkler Umgebung zu hell und bei Tageslicht schlecht sichtbar * Das Setzen von LEDs und Tastendrücke können verschluckt werden * Taster ** Können auch von der Gehäuseunterseite betätigt werden ** Relativ laut (im Video hörbar) ** Wackeln, sind schief und haben keine Führung * Software ** An allen Ecken und Enden rudimentär, wenn etwas ausfällt, funktioniert erst einmal nichts ** Kein automatisches Verbinden mit OBS und der Hardware ** Keine GUI für die Konfiguration ** So gut wie keine Funktionen in OBS unterstützt ** Außer OBS-Steuerung keine weiteren Funktionen * Keine Standby-States =Downloads= * [[Datei:Anykeyx6.zip]] SketchUp-Dateien, zugehörige STLs, Firmware und C#-Software um mit OBS zu sprechen. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] 380e3a0c0b29f674d4690e1442516f0723e2bfbf Datei:Anykeyx6.zip 6 702 1581 2020-05-10T20:06:16Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Anykey x6/en 0 703 1586 2020-05-11T18:19:10Z Chris 2 Page created wikitext text/x-wiki ''This is an translation of [[Anykey x6]], mostly done with the free version of deepl.com and some proofreading.'' [[Datei:anykeyx6_komplett.jpg|thumb|Completely assembled hardware (colors slightly retouched)]] My sister is a teacher. A job I don't envy her for - especially in 2020. Here in Bavaria life at school is slowly starting again (as of the beginning of May), but in parallel to the classes in the schools the children who stay at home have to be taught as well. If you take your own work seriously, this is no fun. Sure, you could simply throw worksheets over the fence and refer to pages in the textbooks, but when I think of my own school days and the rather extrinsic motivation... Although my sister has a lot of digital material, teaching (especially languages) needs someone who speaks in front of the class and of course independent learning isn't easy for everyone. That's why she started making videos. At first only with printed sheets and the mobile phone on the tripod. To be able to use her digital materials better, she asked for a screen recorder. [https://obsproject.com/ OBS] was quickly installed and set up. Too bad she doesn't have a second monitor (or display port adapter) for her MS Surface. So that her students can see her (or even do "blackboard lessons"), I created several scenes in OBS: * Screen recording * Screen recording + camera in the corner * Camera The only stupid thing is that without that second screen she has to bring OBS to the foreground for every action. You could also create global hotkeys, but without a full keyboard you run the risk of getting double assignments and thus have very strange behaviour on the PC. At the same time you don't see what OBS is actually doing. Yes, you can install a remote control for OBS on your tablet or smartphone, but this only creates more problems than it solves, especially since you have to reconfigure the (free) clients I found right away for each session. Furthermore the device has to stay on and there are no physical buttons to feel. This is unnecessarily distracting and does not really increase acceptance. Even ready-made solutions like the Elgato Stream Deck are disproportionately expensive for the (hopefully) short period of use. At the same time, there is an engineer sitting around here who, due to the current situation, is reducing flextime. =The idea= How about some tinkering? A few buttons, a few LEDs, a little firmware and a few lines of code on the PC. Why should it be so complex? Well, let's get one thing straight: If you go beyond your objective it's gonna take a lot of work. The goal is to have 6-8 colorfully illuminated buttons that can be integrated into OBS. The microcontroller was easy to select. To be not too far from the code examples of [https://www.obdev.at/products/vusb/index-en.html V-USB], a vintage ATmega8 is the way to go. Since I wanted to do something with intelligent LEDs for a long time, there is a strip with WS2812B lying around way too long. The plan was to glue it - maybe even still on the strip - on push buttons. Of course, the [[wpen:Woman acceptance factor|WAF]] must fit somehow, so a not too shabby housing is crucial. Thanks to a 3D printer, I'm able to do this (at least in terms of the equipment). =Electronics= The disillusionment came faster than expected. I knew that the timing of the LEDs is critical. That this also applies to V-USB, too. That it is not so easy to combine the two came clear very quickly. The USB stack absolutely needs a pin interrupt, but to control the LEDs, it must be switched off - otherwise everything flashes like a Christmas tree on LSD. Tim (aka cpldcpu) has taken the effort to enable V-USB with [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling] - even with a corresponding LED. I didn't want to go that way because it could potentially be painful in other places. Ok, what now? A coprocessor that converts UART/I²C to the LED protocol? Actually, I didn't want to build a multiprocessor system - and again, the problem with interrupts vs. no interrupts remains, also due to the limitations of USI, this might be a bit uptight. Good advice is expensive. But I didn't want to go back to single-color LEDs either. ==LED driver== To control 6 RGB LEDs with PWM, 18 PWM channels are required. I don't think any AVR8 supports that. I have a PCA9685 lying around, providing only 16 channels. In addition the component with its breakout board takes quite a lot of space. Too much for what I have in mind. Have I written 18 channels? Yes and no. When multiplexing, between 3 and 6 are sufficient. Finally, I decided to take the colors into multiplex and let the PWM run per key - with corresponding losses of brightness (one third). But where do you get 6 synchronous PWM channels on an ATmega8? Very simple: not at all. At least in hardware - it looks different in software, where it's not a real PWM, but rather a pulse power modulation (short PPM - I could find a suitable term, hence the new creation, not to confuse with parts per million or pulse-position modulation, the German abbreviation works a little better), as it was already described in 2011 on the German [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite]. To describe it briefly: with normal PWM there are two switching points for each channel, one of which is individual for each channel (because it determines the brightness value). If you have n channels, there are n points in time which you have to hit as accurately as possible. Especially if they are close together, this can lead to timing problems. The dimmer used here works differently. You have to keep in mind that when dimming LEDs, it doesn't matter if they are on for a cycle at a time or if they are switched off in between - important is how much they are active during a cycle. With a resolution of b bit, this method gives you b points in time - no matter how many channels you use and: their timing is fixed. In addition, they are always separated in time by a factor of 2. Now the channel is always switched on when the "bit" of the corresponding time slot is active in the brightness value. Since the explanation works much better visually than with text, here are two examples with a 3 bit modulation. The valence is on the left, the on times correspond to the green blocks (whose x-axis corresponds to the time) and the necessary interrupts are marked with red arrows: <gallery> anykeyx6_pwm.png | Pulse width modulation anykeyx6_plm.png | Pulse power modulation </gallery> If you look at the active area of the individual brightness values, you come to the same total area - only that the PPM has a significantly higher efficiency. In addition, there is the effect that by "chopping" the PWM, the LEDs flicker at a higher frequency (even if it varies). This reduces the stroboscopic effect - one person's joy is another's misfortune: considering EMC it becomes more uncomfortable at that point. But enough about that. Due to multiplexing, there is, as described above, only a third of the brightness. Most LEDs can handle much more current when driven with pulses than in continuous operation because the limiting factor is heat. Since the LEDs (in the 5050 package) were "harvested" from a LED strip for the assembly, I don't have a datasheet for them, but knowledge: e.g. a 330 Ohm resistor is used for the red strand, with 12 V and 3 red LEDs in series with approx. 1.85 V forward voltage each this is about 20 mA. Without further information about maximum currents and because the brightness should be enough, I stayed with this current. ==Switches== The buttons are connected directly to IOs and are wired to ground. A rudimentary debouncing is done in software. ==USB== The USB circuitry corresponds as far as possible to the examples from Objective Development. Out of sheer laziness I took over the protection circuitry from the [[USB-Fußtaster|USB foot switch]]. Proverbially: I assembled the necessary components and trimmed the circuit board to the right size. ==Circuit diagram== So the whole circuit is relatively simple. The FETs for the LEDs are BSS84 (p-channel, on the anode side) and BSS138 (n-channel, on the cathode side). Because of the simplicity a hand sketch does the job: <gallery> anykeyx6_sch.png | schematic - unknown artist, 2020, digital </gallery> =Firmware= The firmware is surprisingly simple, especially since I didn't try very hard. The LEDs are controlled with the method described above (in leddrv.c), with an additional fading function. This relieves the USB stack and reduces flickering (see below) The keys are polled (unless PWM has higher priority) every millisecond (<code>buttons_tick()</code>). In case the level is low (key pressed), a counter is incremented. If the level is high, the counter is reset to 0. If the counter is greater than 10, the corresponding key is considered pressed. All buttons in one byte can be queried via the method <code>buttons_values()</code>. As far as USB is concerned, an Out-Report (PC -> Device) with net 16 bytes and an In-Report with net 8 bytes (Device -> PC) is used. The Out-Report is used to set the LEDs and looks as follows: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index of the LED (1-6) * <span class="hb2">Rx</span>: Red value of the LED (0 ... 255) * <span class="hb3">Gx</span>: Green value of the LED (0 ... 255) * <span class="hb4">Bx</span>: Blue value of the LED (0 ... 255) * <span class="hb5">Tx</span>: Duration for the transition (0 ... 255, in 5 ms steps) This way, colors for 3 buttons can be written at once, index 0 is not used, because it is usually the init value for arrays and therefore the color of a key is not set by mistake. The in-report is very simple, the first byte contains the bit pattern of the currently pressed buttons: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> The report is sent every time the status of the buttons changes. This is not quite ideal in several respects, because on the one hand the initial state (after opening the device) cannot be determined and on the other hand, if a USB packet is lost, you miss keystrokes. But: it had to be implemented quickly. == Mechanics== The mechanics are (at least for me as a noob to design and 3D printing) a bit more complex. Just banging the circuit board on the table is not possible here, it doesn't have to look spick and span, but it shouldn't completely be "form follows function". To get ahead quickly, the MS Paint in 3D design was used: SketchUp. With all the limitations and lack of parameterization, it's still the fastest way for me to prepare something for printing. ==Keys== With a little drawing in 2D software, it turned out that rectangular keys with a width and height of 15 mm, a rounding with a radius of 2.5 mm and a distance of 5 mm to each other have a pleasant look & feel. A first pattern with a collar (so the key doesn't fall through the case) with transparent PLA, (if I remember correctly) 50 % infill and concentric top/bottom pattern (sliced in Cura) is printed quickly and looks, after being smeared with ink to see how tight the print is, dirty even after cleaning. Light goes through, but looks rather modest: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Illumination with concentric printing pattern </gallery> Next comes the question: how to assemble the LEDs and switches? to simplify the mechanics, I followed the idea of using common parts where possible. In my last PCB orders I always placed 1x1 mm copper areas in the waste in a 1.27 mm grid, a strip with this is about 9.6 mm wide (with 1.6 mm material thickness) - a good size for this application. LED on one side, buttons on the other and an idea for which the designers at work would probably (quite rightly) not look at me anymore: Constraining on two reference planes. Normally, you aim to have the tolerances spread out from one side so that you can keep the tolerance chains under control. Would mean here: The keys are referenced to the front of the case and accordingly, the keys have to be mounted on a plane whose tolerance refers to the front. But in my case the keys should press against the base plate. With many disadvantages. Since it is currently however a single piece: No matter. The PCB with LED in the front and switch in the back is simply inserted into a groove in the button. Except for a small (reproducible) printing error, this works perfectly. Here are the different design iterations: <gallery. anykeyx6_taste_iterationen.jpg | iterations of keys 1 to 5.5 anykeyx6_sketchup_taste_seite.png | Final model of the keys from the side anykeyx6_sketchup_taster_unten.png | and from below anykeyx6_taste_einzelteile.jpg | individual parts of the keys (w/o switch) anykeyx6_taste_LED.jpg | circuit board inserted into the button </gallery> With infill set to 100 % and the button front on the printing bed, a relatively nice surface is created. Since Concentric Top/Bottom-Pattern created a cross in the diagonal, I switched to "Lines", which, together with the concentric frame, makes the push buttons look almost "like a bought one". In order to achieve better color mixing (and the buttons have a strange scattering effect), I glued some tape from my label printer (if it is important: Brother P-touch) behind the button. This makes the illumination of the three LED crystals at least a bit more homogeneous: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | For comparison again the picture from above (concentric printing pattern) anykeyx6_beleuchtung_diffusor.jpg | left without, right with tape </gallery> In total the sandwich has a height of 12.4 mm - 0.25 mm less when the button is pressed. The collar is offset 2.5 mm to the inside. This, plus the thickness of the case parts, becomes the total thickness of the device. =Housing= The dimensions of the buttons are the starting point, with the cut-outs for them extended by 0.25 mm in all directions. This brings some play, but before the cutter has to be attached or printed again, the keys may wobble a little - especially since there were some elephant feet in the first keys. With a projection of 7.5 mm from the edge of the buttons to the case walls in three directions and a little more (17.5 mm) in the fourth direction - the electronics have to go somewhere - the case is relatively compact. Inside, there are 4 mm high walls between the buttons - not for alignment, but rather to avoid stray light between the buttons. To prevent the housing from bending and thus accidentally actuating several buttons at once, there are elevations in the crossing points of the buttons which increase stability in the Z-direction. To save material and especially printing time, there were two cut-off test prints, which are almost invisible on a white background on white background thanks to the transparent filament: <gallery> anykeyx6_druckmuster_deckel.jpg | Print pattern for the keys </gallery> As strain relief for the permanently installed USB cable, there is a small ramp behind the U-shaped cut-out and a hole through for a cable tie. The ramp only serves to prevent the cable tie from pressing down the lower half of the housing. One could speculate that the stair structure caused by the print layers might even help the cable to not slip out. 3 holes, through which M2.5 screws fit, are used to hold everything together. There were 4 iterations in total, but only two of them found their way to the printer - and that only because the first part lifted off the printing bed and thus was warped. Apparently the STL data is not quite clean, so the model is probably a bit hanging in the air. With a microstep of -0.001 in the Z-direction, the printing result was better, but the first layer is still a bit grubby... <gallery> anykeyx6_sketchup_deckel.png | 3D model of the upper shell anykeyx6_deckel_vergurkt.jpg | The first try (warped) anykeyx6_Deckel.jpg | The better print. </gallery> The lower part of the case is actually 7 parts and needed no revision (but a small operation with the scalpel). The complexity is also much lower. The 4 "chimneys" are striking at first - the idea behind them is to insert nuts and screw them to the upper part of the case. The whole thing is (rather unintentionally) designed for compression, both for the nut and towards the other part of the housing. At least nothing slips. There are blind holes/indents at the positions of the buttons - for a very simple reason: save material and print time. The base plate should be thick enough to be stable but not to have to be printed a second time. In order to fit the buttons in height, small spacer nipples are used, which are small and therefore can be adjusted and printed very quickly. Because I didn't have any super glue left, they are only fixed on one side on the base plate with double sided adhesive tape. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D model of the bottom plate anykeyx6_shim.png | The 3D model of a nipple anykeyx6_bodenplatte_benippelt.jpg | Floor plate with nuts and nipples (and I thought this was bad in German) </gallery> All in all, the printer was busy for about 4 hours, although it was not running at maximum speed. The material costs are (without samples and misprints) about 50 cent if I am not mistaken, so not really worth mentioning. =Assembly= Originally I planned to use an Atmega8 in a DIP package. But since it would have been a bit tight, I decided to use one in a TQFP package. Besides the microcontroller, the 9 transistors for LED control are also located on the self-made dot matrix board: <gallery> anykeyx6_platine.jpg | Assembled circuit board </gallery> The LED keys are fitted with long connecting leads made of enamelled copper wire, which are beeped through and stuck on correspondingly labelled tape strips. Twisted and soldered together, they then are connected the FETs. Same procedure for the ground of the switches. <gallery> anykeyx6_tastenverdrahtung.jpg | Tidying up the chaos </gallery> To prevent the keys from repeatedly slipping out of their holes when the housing is closed, tape is applied to the outside of the case. For safety reasons, it is labeled with numbers so that nothing can go wrong with turning and mirroring. Keys inserted, cables laid in the case and the copper ball is formed. Cable spaghetti, anyone? The USB cable is firmly lashed down and has a very tight bending radius in the case - it's in (hopefully). <gallery> anykeyx6_boden_und_deckel.jpg | both halves of the housing anykeyx6_deckel_verklebt.jpg | some assembly aid anykeyx6_deckel_assy.jpg | lid with inserted components </gallery> The nipples are already glued into the lower half of the housing and it gets exciting: does it fit? Unfortunately there are no countersunk screws in the part box, so it remains a bit ugly with the galvanized cylinder head screws. Or pragmatic. Well, it holds - and the buttons are in the case in such a way that they neither (too much) rattle nor are they pressed permanently. Success! :) To give the buttons some more meaning, the upper row is decorated with a label of some symbols from FontAwesome. Now nothing should go wrong. =Software= ==first test== The first test software is written in Python and lets a rainbow run through. For the sake of simplicity, it only changes one LED at a time: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> As a snapshot, it looks something like this: <gallery> anykeyx6_rgb_demo.jpg | colors, yay! </gallery> ==The OBS Client== Due to the lack of deep knowledge in C++, I don't even try to write a real plugin for OBS. Instead I use [https://github.com/Palakis/obs-websocket obs-websocket], which provides an API for C# that is extremely easy to use. For the buttons, an extremely rudimentary class is hacked together. No error handling at all. The buttons are read out in a background worker that fires events (and also determines the duration of the press when released), the LED colors are set for all 6 buttons in one method. Here you can also see how hastily cobbled together it is: Between writing the two "sets" of color, the software sleeps for a millisecond. The reason is both simply and stupid: if you write too fast, the first of the two data packets may be lost in the firmware, because the transfer is not (if you want to call it that) threadsafe. The GUI only has a "Connect" button that should only be pressed when OBS is running and the hardware is connected. The configuration is also rather basic and can be found in AnykeyOBS.exe.config Here you can store the active/inactive colors for each button as hex code (or named color, untested), define the function and give an argument for this function. To assign a scene, pack into the function "Scene" and write the corresponding scene name into the argument. For recording, the function is called "Record" and the argument can be defined as "Toggle", "Start" and "Stop". Streaming is not yet supported. For reasons not quite understandable to me, the state of streaming/recording can only be determined by events. Therefore, the key with the corresponding assignment remains orange when the program is started. This is also the (hard coded) color for transitions between recording and no recording. Another feature is the cancelling of actions - basically they are only triggered when the button is released - unless the button is held for more than one second. In this case the action is cancelled. All in all, the software can at best be described as a proof of concept. It works, somehow. ===First fire=== In the meantime I was even allowed to visit my sister to give her the hardware. yay! But the setup was done online, though. Got obs-websocks installed, copied AnykeyOBS on the tablet and: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Shit. The presumed cause is quickly located: Some USB devices' name can't be read. Thrown a pack of try-catch on the problem and a pinch of <code>Console.WriteLine</code>s and the program stays open after clicking "Connect". "Do the buttons light up?" - "Oh man, how cool" - "So yes?" After that I only heard wild clicking. I think she likes it. And this is what it looks like: [[Datei:anykeyx6_demo.mp4]] =Conclusion= Where to start? For the good, the bad or the things I'm ashamed of? Bottom line: for a very shirt-sleeved piece of hardware, it looks (without me wanting to praise myself) quite decent. It only gets bad when you look under the hood. But at least that's pretty consistent. The good: * My sister has something that I hope will make her job a little easier * I've learned a about 3D printing again * It's been a lot of fun * It's quite colorful The bad: * Decoupling, what decoupling? * LEDs ** Not very bright ** Flickering during USB traffic (due to INT0) ** Too bright in dark surroundings and poorly visible in bright daylight * Changes of dropped packets for LED settings and key presses are quite high * Buttons ** Can also be operated from the bottom of the housing ** Relatively loud (can be heard in the video) ** Wobble, are crooked and have no guidance * Software ** Rudimentary in all manners, if anything fails, everything's gone ** No automatic connection to OBS and the hardware ** No GUI for configuration ** Virtually no functions supported in OBS ** No other functions except OBS control * No standby states =Downloads= * [[Datei:Anykeyx6.zip]] SketchUp files, associated STLs, firmware and C# software to talk to OBS. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] [[Kategorie:English translation]] e44fc95ea272a797995daf8d4f4d61f94974c454 1589 1586 2020-05-11T18:27:19Z Chris 2 fixed interwiki-link wikitext text/x-wiki ''This is an translation of [[Anykey x6]], mostly done with the free version of deepl.com and some proofreading.'' [[Datei:anykeyx6_komplett.jpg|thumb|Completely assembled hardware (colors slightly retouched)]] My sister is a teacher. A job I don't envy her for - especially in 2020. Here in Bavaria life at school is slowly starting again (as of the beginning of May), but in parallel to the classes in the schools the children who stay at home have to be taught as well. If you take your own work seriously, this is no fun. Sure, you could simply throw worksheets over the fence and refer to pages in the textbooks, but when I think of my own school days and the rather extrinsic motivation... Although my sister has a lot of digital material, teaching (especially languages) needs someone who speaks in front of the class and of course independent learning isn't easy for everyone. That's why she started making videos. At first only with printed sheets and the mobile phone on the tripod. To be able to use her digital materials better, she asked for a screen recorder. [https://obsproject.com/ OBS] was quickly installed and set up. Too bad she doesn't have a second monitor (or display port adapter) for her MS Surface. So that her students can see her (or even do "blackboard lessons"), I created several scenes in OBS: * Screen recording * Screen recording + camera in the corner * Camera The only stupid thing is that without that second screen she has to bring OBS to the foreground for every action. You could also create global hotkeys, but without a full keyboard you run the risk of getting double assignments and thus have very strange behaviour on the PC. At the same time you don't see what OBS is actually doing. Yes, you can install a remote control for OBS on your tablet or smartphone, but this only creates more problems than it solves, especially since you have to reconfigure the (free) clients I found right away for each session. Furthermore the device has to stay on and there are no physical buttons to feel. This is unnecessarily distracting and does not really increase acceptance. Even ready-made solutions like the Elgato Stream Deck are disproportionately expensive for the (hopefully) short period of use. At the same time, there is an engineer sitting around here who, due to the current situation, is reducing flextime. =The idea= How about some tinkering? A few buttons, a few LEDs, a little firmware and a few lines of code on the PC. Why should it be so complex? Well, let's get one thing straight: If you go beyond your objective it's gonna take a lot of work. The goal is to have 6-8 colorfully illuminated buttons that can be integrated into OBS. The microcontroller was easy to select. To be not too far from the code examples of [https://www.obdev.at/products/vusb/index-en.html V-USB], a vintage ATmega8 is the way to go. Since I wanted to do something with intelligent LEDs for a long time, there is a strip with WS2812B lying around way too long. The plan was to glue it - maybe even still on the strip - on push buttons. Of course, the [[wikipedia:Woman acceptance factor|WAF]] must fit somehow, so a not too shabby housing is crucial. Thanks to a 3D printer, I'm able to do this (at least in terms of the equipment). =Electronics= The disillusionment came faster than expected. I knew that the timing of the LEDs is critical. That this also applies to V-USB, too. That it is not so easy to combine the two came clear very quickly. The USB stack absolutely needs a pin interrupt, but to control the LEDs, it must be switched off - otherwise everything flashes like a Christmas tree on LSD. Tim (aka cpldcpu) has taken the effort to enable V-USB with [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling] - even with a corresponding LED. I didn't want to go that way because it could potentially be painful in other places. Ok, what now? A coprocessor that converts UART/I²C to the LED protocol? Actually, I didn't want to build a multiprocessor system - and again, the problem with interrupts vs. no interrupts remains, also due to the limitations of USI, this might be a bit uptight. Good advice is expensive. But I didn't want to go back to single-color LEDs either. ==LED driver== To control 6 RGB LEDs with PWM, 18 PWM channels are required. I don't think any AVR8 supports that. I have a PCA9685 lying around, providing only 16 channels. In addition the component with its breakout board takes quite a lot of space. Too much for what I have in mind. Have I written 18 channels? Yes and no. When multiplexing, between 3 and 6 are sufficient. Finally, I decided to take the colors into multiplex and let the PWM run per key - with corresponding losses of brightness (one third). But where do you get 6 synchronous PWM channels on an ATmega8? Very simple: not at all. At least in hardware - it looks different in software, where it's not a real PWM, but rather a pulse power modulation (short PPM - I could find a suitable term, hence the new creation, not to confuse with parts per million or pulse-position modulation, the German abbreviation works a little better), as it was already described in 2011 on the German [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite]. To describe it briefly: with normal PWM there are two switching points for each channel, one of which is individual for each channel (because it determines the brightness value). If you have n channels, there are n points in time which you have to hit as accurately as possible. Especially if they are close together, this can lead to timing problems. The dimmer used here works differently. You have to keep in mind that when dimming LEDs, it doesn't matter if they are on for a cycle at a time or if they are switched off in between - important is how much they are active during a cycle. With a resolution of b bit, this method gives you b points in time - no matter how many channels you use and: their timing is fixed. In addition, they are always separated in time by a factor of 2. Now the channel is always switched on when the "bit" of the corresponding time slot is active in the brightness value. Since the explanation works much better visually than with text, here are two examples with a 3 bit modulation. The valence is on the left, the on times correspond to the green blocks (whose x-axis corresponds to the time) and the necessary interrupts are marked with red arrows: <gallery> anykeyx6_pwm.png | Pulse width modulation anykeyx6_plm.png | Pulse power modulation </gallery> If you look at the active area of the individual brightness values, you come to the same total area - only that the PPM has a significantly higher efficiency. In addition, there is the effect that by "chopping" the PWM, the LEDs flicker at a higher frequency (even if it varies). This reduces the stroboscopic effect - one person's joy is another's misfortune: considering EMC it becomes more uncomfortable at that point. But enough about that. Due to multiplexing, there is, as described above, only a third of the brightness. Most LEDs can handle much more current when driven with pulses than in continuous operation because the limiting factor is heat. Since the LEDs (in the 5050 package) were "harvested" from a LED strip for the assembly, I don't have a datasheet for them, but knowledge: e.g. a 330 Ohm resistor is used for the red strand, with 12 V and 3 red LEDs in series with approx. 1.85 V forward voltage each this is about 20 mA. Without further information about maximum currents and because the brightness should be enough, I stayed with this current. ==Switches== The buttons are connected directly to IOs and are wired to ground. A rudimentary debouncing is done in software. ==USB== The USB circuitry corresponds as far as possible to the examples from Objective Development. Out of sheer laziness I took over the protection circuitry from the [[USB-Fußtaster|USB foot switch]]. Proverbially: I assembled the necessary components and trimmed the circuit board to the right size. ==Circuit diagram== So the whole circuit is relatively simple. The FETs for the LEDs are BSS84 (p-channel, on the anode side) and BSS138 (n-channel, on the cathode side). Because of the simplicity a hand sketch does the job: <gallery> anykeyx6_sch.png | schematic - unknown artist, 2020, digital </gallery> =Firmware= The firmware is surprisingly simple, especially since I didn't try very hard. The LEDs are controlled with the method described above (in leddrv.c), with an additional fading function. This relieves the USB stack and reduces flickering (see below) The keys are polled (unless PWM has higher priority) every millisecond (<code>buttons_tick()</code>). In case the level is low (key pressed), a counter is incremented. If the level is high, the counter is reset to 0. If the counter is greater than 10, the corresponding key is considered pressed. All buttons in one byte can be queried via the method <code>buttons_values()</code>. As far as USB is concerned, an Out-Report (PC -> Device) with net 16 bytes and an In-Report with net 8 bytes (Device -> PC) is used. The Out-Report is used to set the LEDs and looks as follows: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index of the LED (1-6) * <span class="hb2">Rx</span>: Red value of the LED (0 ... 255) * <span class="hb3">Gx</span>: Green value of the LED (0 ... 255) * <span class="hb4">Bx</span>: Blue value of the LED (0 ... 255) * <span class="hb5">Tx</span>: Duration for the transition (0 ... 255, in 5 ms steps) This way, colors for 3 buttons can be written at once, index 0 is not used, because it is usually the init value for arrays and therefore the color of a key is not set by mistake. The in-report is very simple, the first byte contains the bit pattern of the currently pressed buttons: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> The report is sent every time the status of the buttons changes. This is not quite ideal in several respects, because on the one hand the initial state (after opening the device) cannot be determined and on the other hand, if a USB packet is lost, you miss keystrokes. But: it had to be implemented quickly. == Mechanics== The mechanics are (at least for me as a noob to design and 3D printing) a bit more complex. Just banging the circuit board on the table is not possible here, it doesn't have to look spick and span, but it shouldn't completely be "form follows function". To get ahead quickly, the MS Paint in 3D design was used: SketchUp. With all the limitations and lack of parameterization, it's still the fastest way for me to prepare something for printing. ==Keys== With a little drawing in 2D software, it turned out that rectangular keys with a width and height of 15 mm, a rounding with a radius of 2.5 mm and a distance of 5 mm to each other have a pleasant look & feel. A first pattern with a collar (so the key doesn't fall through the case) with transparent PLA, (if I remember correctly) 50 % infill and concentric top/bottom pattern (sliced in Cura) is printed quickly and looks, after being smeared with ink to see how tight the print is, dirty even after cleaning. Light goes through, but looks rather modest: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Illumination with concentric printing pattern </gallery> Next comes the question: how to assemble the LEDs and switches? to simplify the mechanics, I followed the idea of using common parts where possible. In my last PCB orders I always placed 1x1 mm copper areas in the waste in a 1.27 mm grid, a strip with this is about 9.6 mm wide (with 1.6 mm material thickness) - a good size for this application. LED on one side, buttons on the other and an idea for which the designers at work would probably (quite rightly) not look at me anymore: Constraining on two reference planes. Normally, you aim to have the tolerances spread out from one side so that you can keep the tolerance chains under control. Would mean here: The keys are referenced to the front of the case and accordingly, the keys have to be mounted on a plane whose tolerance refers to the front. But in my case the keys should press against the base plate. With many disadvantages. Since it is currently however a single piece: No matter. The PCB with LED in the front and switch in the back is simply inserted into a groove in the button. Except for a small (reproducible) printing error, this works perfectly. Here are the different design iterations: <gallery. anykeyx6_taste_iterationen.jpg | iterations of keys 1 to 5.5 anykeyx6_sketchup_taste_seite.png | Final model of the keys from the side anykeyx6_sketchup_taster_unten.png | and from below anykeyx6_taste_einzelteile.jpg | individual parts of the keys (w/o switch) anykeyx6_taste_LED.jpg | circuit board inserted into the button </gallery> With infill set to 100 % and the button front on the printing bed, a relatively nice surface is created. Since Concentric Top/Bottom-Pattern created a cross in the diagonal, I switched to "Lines", which, together with the concentric frame, makes the push buttons look almost "like a bought one". In order to achieve better color mixing (and the buttons have a strange scattering effect), I glued some tape from my label printer (if it is important: Brother P-touch) behind the button. This makes the illumination of the three LED crystals at least a bit more homogeneous: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | For comparison again the picture from above (concentric printing pattern) anykeyx6_beleuchtung_diffusor.jpg | left without, right with tape </gallery> In total the sandwich has a height of 12.4 mm - 0.25 mm less when the button is pressed. The collar is offset 2.5 mm to the inside. This, plus the thickness of the case parts, becomes the total thickness of the device. =Housing= The dimensions of the buttons are the starting point, with the cut-outs for them extended by 0.25 mm in all directions. This brings some play, but before the cutter has to be attached or printed again, the keys may wobble a little - especially since there were some elephant feet in the first keys. With a projection of 7.5 mm from the edge of the buttons to the case walls in three directions and a little more (17.5 mm) in the fourth direction - the electronics have to go somewhere - the case is relatively compact. Inside, there are 4 mm high walls between the buttons - not for alignment, but rather to avoid stray light between the buttons. To prevent the housing from bending and thus accidentally actuating several buttons at once, there are elevations in the crossing points of the buttons which increase stability in the Z-direction. To save material and especially printing time, there were two cut-off test prints, which are almost invisible on a white background on white background thanks to the transparent filament: <gallery> anykeyx6_druckmuster_deckel.jpg | Print pattern for the keys </gallery> As strain relief for the permanently installed USB cable, there is a small ramp behind the U-shaped cut-out and a hole through for a cable tie. The ramp only serves to prevent the cable tie from pressing down the lower half of the housing. One could speculate that the stair structure caused by the print layers might even help the cable to not slip out. 3 holes, through which M2.5 screws fit, are used to hold everything together. There were 4 iterations in total, but only two of them found their way to the printer - and that only because the first part lifted off the printing bed and thus was warped. Apparently the STL data is not quite clean, so the model is probably a bit hanging in the air. With a microstep of -0.001 in the Z-direction, the printing result was better, but the first layer is still a bit grubby... <gallery> anykeyx6_sketchup_deckel.png | 3D model of the upper shell anykeyx6_deckel_vergurkt.jpg | The first try (warped) anykeyx6_Deckel.jpg | The better print. </gallery> The lower part of the case is actually 7 parts and needed no revision (but a small operation with the scalpel). The complexity is also much lower. The 4 "chimneys" are striking at first - the idea behind them is to insert nuts and screw them to the upper part of the case. The whole thing is (rather unintentionally) designed for compression, both for the nut and towards the other part of the housing. At least nothing slips. There are blind holes/indents at the positions of the buttons - for a very simple reason: save material and print time. The base plate should be thick enough to be stable but not to have to be printed a second time. In order to fit the buttons in height, small spacer nipples are used, which are small and therefore can be adjusted and printed very quickly. Because I didn't have any super glue left, they are only fixed on one side on the base plate with double sided adhesive tape. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D model of the bottom plate anykeyx6_shim.png | The 3D model of a nipple anykeyx6_bodenplatte_benippelt.jpg | Floor plate with nuts and nipples (and I thought this was bad in German) </gallery> All in all, the printer was busy for about 4 hours, although it was not running at maximum speed. The material costs are (without samples and misprints) about 50 cent if I am not mistaken, so not really worth mentioning. =Assembly= Originally I planned to use an Atmega8 in a DIP package. But since it would have been a bit tight, I decided to use one in a TQFP package. Besides the microcontroller, the 9 transistors for LED control are also located on the self-made dot matrix board: <gallery> anykeyx6_platine.jpg | Assembled circuit board </gallery> The LED keys are fitted with long connecting leads made of enamelled copper wire, which are beeped through and stuck on correspondingly labelled tape strips. Twisted and soldered together, they then are connected the FETs. Same procedure for the ground of the switches. <gallery> anykeyx6_tastenverdrahtung.jpg | Tidying up the chaos </gallery> To prevent the keys from repeatedly slipping out of their holes when the housing is closed, tape is applied to the outside of the case. For safety reasons, it is labeled with numbers so that nothing can go wrong with turning and mirroring. Keys inserted, cables laid in the case and the copper ball is formed. Cable spaghetti, anyone? The USB cable is firmly lashed down and has a very tight bending radius in the case - it's in (hopefully). <gallery> anykeyx6_boden_und_deckel.jpg | both halves of the housing anykeyx6_deckel_verklebt.jpg | some assembly aid anykeyx6_deckel_assy.jpg | lid with inserted components </gallery> The nipples are already glued into the lower half of the housing and it gets exciting: does it fit? Unfortunately there are no countersunk screws in the part box, so it remains a bit ugly with the galvanized cylinder head screws. Or pragmatic. Well, it holds - and the buttons are in the case in such a way that they neither (too much) rattle nor are they pressed permanently. Success! :) To give the buttons some more meaning, the upper row is decorated with a label of some symbols from FontAwesome. Now nothing should go wrong. =Software= ==first test== The first test software is written in Python and lets a rainbow run through. For the sake of simplicity, it only changes one LED at a time: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> As a snapshot, it looks something like this: <gallery> anykeyx6_rgb_demo.jpg | colors, yay! </gallery> ==The OBS Client== Due to the lack of deep knowledge in C++, I don't even try to write a real plugin for OBS. Instead I use [https://github.com/Palakis/obs-websocket obs-websocket], which provides an API for C# that is extremely easy to use. For the buttons, an extremely rudimentary class is hacked together. No error handling at all. The buttons are read out in a background worker that fires events (and also determines the duration of the press when released), the LED colors are set for all 6 buttons in one method. Here you can also see how hastily cobbled together it is: Between writing the two "sets" of color, the software sleeps for a millisecond. The reason is both simply and stupid: if you write too fast, the first of the two data packets may be lost in the firmware, because the transfer is not (if you want to call it that) threadsafe. The GUI only has a "Connect" button that should only be pressed when OBS is running and the hardware is connected. The configuration is also rather basic and can be found in AnykeyOBS.exe.config Here you can store the active/inactive colors for each button as hex code (or named color, untested), define the function and give an argument for this function. To assign a scene, pack into the function "Scene" and write the corresponding scene name into the argument. For recording, the function is called "Record" and the argument can be defined as "Toggle", "Start" and "Stop". Streaming is not yet supported. For reasons not quite understandable to me, the state of streaming/recording can only be determined by events. Therefore, the key with the corresponding assignment remains orange when the program is started. This is also the (hard coded) color for transitions between recording and no recording. Another feature is the cancelling of actions - basically they are only triggered when the button is released - unless the button is held for more than one second. In this case the action is cancelled. All in all, the software can at best be described as a proof of concept. It works, somehow. ===First fire=== In the meantime I was even allowed to visit my sister to give her the hardware. yay! But the setup was done online, though. Got obs-websocks installed, copied AnykeyOBS on the tablet and: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Shit. The presumed cause is quickly located: Some USB devices' name can't be read. Thrown a pack of try-catch on the problem and a pinch of <code>Console.WriteLine</code>s and the program stays open after clicking "Connect". "Do the buttons light up?" - "Oh man, how cool" - "So yes?" After that I only heard wild clicking. I think she likes it. And this is what it looks like: [[Datei:anykeyx6_demo.mp4]] =Conclusion= Where to start? For the good, the bad or the things I'm ashamed of? Bottom line: for a very shirt-sleeved piece of hardware, it looks (without me wanting to praise myself) quite decent. It only gets bad when you look under the hood. But at least that's pretty consistent. The good: * My sister has something that I hope will make her job a little easier * I've learned a about 3D printing again * It's been a lot of fun * It's quite colorful The bad: * Decoupling, what decoupling? * LEDs ** Not very bright ** Flickering during USB traffic (due to INT0) ** Too bright in dark surroundings and poorly visible in bright daylight * Changes of dropped packets for LED settings and key presses are quite high * Buttons ** Can also be operated from the bottom of the housing ** Relatively loud (can be heard in the video) ** Wobble, are crooked and have no guidance * Software ** Rudimentary in all manners, if anything fails, everything's gone ** No automatic connection to OBS and the hardware ** No GUI for configuration ** Virtually no functions supported in OBS ** No other functions except OBS control * No standby states =Downloads= * [[Datei:Anykeyx6.zip]] SketchUp files, associated STLs, firmware and C# software to talk to OBS. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] [[Kategorie:English translation]] e3972cb96f8aced0dde677825179f547bd18cd37 Anykey x6 0 701 1590 1588 2020-05-11T18:48:33Z Chris 2 /* Feuerprobe */ Mit Videoplayer wikitext text/x-wiki ''There's also an [[Anykey_x6/en|English translation]] of this article.'' [[Datei:anykeyx6_komplett.jpg|thumb|Fertig aufgebaute Hardware (Farben leicht retuschiert)]] Meine Schwester ist Lehrerin. Ein Job, um den ich sie nicht beneide - gerade in 2020. Hier in Bayern fängt (Stand Anfang Mai) das Leben an der Schule langsam wieder an, parallel zum Unterricht in den Schulen müssen jedoch die daheim bleibenden Kinder noch unterrichtet werden. Wenn man die eigene Arbeit ernst nimmt, ist das kein Spaß. Klar, man könnte für das Eigenstudium einfach Arbeitsblätter über den Zaun werfen und auf Seiten in den Büchern verweisen, aber wenn ich da an meine eigene Schulzeit und die eher extrinsische Motivation denke... Obwohl meine Schwester schon sehr viel digital hat, braucht Unterricht (gerade bei Sprachen) auch jemanden, der/die vor der Klasse spricht und natürlich ist eigenständiges Lernen für viele nicht ganz einfach. Aus diesem Grund hat meine Schwester angefangen, Videos zu machen. Vorerst nur mit ausgedruckten Blättern und dem Handy auf dem Stativ. Um Ihre digitalen Materialien besser nutzen zu können, fragte sie dann doch mal nach einem screen recorder. [https://obsproject.com/ OBS] war schnell installiert und eingerichtet. Blöd nur, dass sie keinen zweiten Monitor (bzw. Displayport-Adapter) für ihr MS Surface hat. Damit ihre Schüler sie auch mal sehen können (oder auch mal "Tafelunterricht" zu machen), habe ich ihr mehrere Szenen in OBS eingerichtet: * Bildschirmaufnahme * Bildschirmaufnahme + Kamera in der Ecke * Kamera Blöd ist nur, dass sie ohne besagten zweiten Bildschirm für jede Aktion OBS in den Vordergrund holen muss. Zwar kann man dort auch globale Hotkeys anlegen, aber ohne vollständige Tastatur läuft man sehr schnell Gefahr, Doppelbelegungen zu bekommen und dadurch sehr merkwürdiges Verhalten am PC zu haben. Gleichzeitig sieht man nicht, was OBS nun tatsächlich macht. Ja, man kann eine Fernbedienung für OBS auf dem Tablet oder Smartphone installieren, aber das schafft eigentlich nur mehr Probleme als es löst, zumal man die (freien) Clients, die ich auf Anhieb gefunden hab für jede Session neu konfigurieren muss. Zudem muss das Gerät am Laufen halten und kann die Tasten nicht erfühlen. Das lenkt unnötig ab und erhöht auch die Akzeptanz nicht wirklich. Auch fertige Lösungen wie das Elgato Stream Deck ist für die (hoffentlich) kurze Nutzungsdauer unverhältnismäßig teuer. Gleichzeitig sitzt hier ein Ingenieur herum, der aufgrund der aktuellen Situation erst einmal Gleitzeit abbaut. =Die Idee= Da kann man doch was basteln. Ein paar Taster, ein paar LEDs, ein bisschen Firmware und noch ein paar Zeilen Code auf dem PC. Was soll daran so aufwändig sein? Um eines vorweg zu nehmen: Übers Ziel hinausschießen, das kann daran aufwändig werden. Ziel ist, 6-8 bunt beleuchtete Taster zu haben, die in OBS eingebunden werden können. Der Mikrocontroller ist schnell gefunden. Um nicht zu weit von den Codebeispielen von [https://www.obdev.at/products/vusb/index-de.html V-USB] zu sein, soll ein oller ATmega8 zum Einsatz kommen. Weil ich schon länger was mit intelligenten LEDs machen wollte, liegt schon viel zu lange ein Streifen mit WS2812B herum. Der Plan war, diese – womöglich sogar noch auf dem Streifen – auf Taster zu kleben. Natürlich muss der [[wpde:Woman acceptance factor|WAF]] auch halbwegs passen, deshalb ist ein nicht zu schäbiges Gehäuse angesagt. 3D-Drucker sei dank bin ich auch dazu (zumindest seitens der Ausstattung) in der Lage. =Elektronik= Die Ernüchterung kam schneller als erwartet. Dass die Ansteuerung der LEDs zeitkritisch ist, wusste ich. Dass das auch für V-USB gilt, ebenfalls. Dass man beides nicht so einfach kombinieren kann, würde dann sehr schnell klar. Der USB-Stack braucht zwingend einen Pin-Interrupt, für die Ansteuerung der LEDs muss dieser aber abgeschaltet werden – sonst blinkt alles wie ein Weihnachtsbaum auf LSD. Tim (aka cpldcpu) hat sich die Mühe gemacht, V-USB mit [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling zu ermöglichen] - gleichzeitig sogar mit entsprechender LED. Den Weg wollte ich nicht gehen, weil das potenziell an anderen Stellen schmerzhaft werden könnte. Ok, was nun? Ein Coprozessor, der UART/I²C auf das LED-Protokoll umwandelt? Eigentlich wollte ich kein Mehrprozessor-System bauen – und auch hier bleibt das Problem mit Interrupts vs. keine Interrupts, auch durch die Einschränkungen durch USI dürfte das noch etwas unentspannter sein. Da ist guter Rat teuer. Auf einfarbige LEDs wollte ich aber auch nicht zurückgehen. ==LED-Treiber== 6 RGB-LEDs mit PWM anzusteuern, braucht es 18 PWM-Kanäle. Das hat glaube ich kein AVR8. ich habe zwar noch einen PCA9685 herumliegen, der aber auch nur 16 Kanäle bereitstellt. Zudem nimmt das Teil mit seinem Breakout-Board relativ viel Platz ein. Zu viel für das, was ich vor dem inneren Auge habe. Habe ich 18 Kanäle geschrieben? Jein. Betreibt man Multiplexing, reichen zwischen 3 und 6. Schlussendlich habe ich mich dafür entschieden, die Farben in den Multiplex zu nehmen und den PWM pro Taste laufen zu lassen - mit entsprechenden Einbußen der Helligkeit (ein Drittel). Aber wo bekommt man an einem ATmega8 6 synchrone PWM-Kanäle her? Ganz einfach: gar nicht. Zumindest in Hardware - anders schaut es in Software aus, wo es auch keine richtige PWM ist, sondern eher eine Pulsleistungsmodulation (kurz PDM - einen passenden Begriff konnte ich finden, daher die Neukreation), wie sie 2011 auf der [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite] schon beschrieben wurde. Um es kurz zu beschreiben: bei gewöhnlicher PWM gibt es für jeden Kanal zwei Schaltzeitpunkte, von denen einer pro Kanal individuell ist (da er den Helligkeitswert vorgibt). Hat man n Kanäle, gibt es n Zeitpunkte, die man möglichst zielgenau treffen muss. Gerade wenn diese nah beieinander liegen, kann das zu Timingproblemen führen. Der hier verwendete Dimmer funktioniert anders. Man muss dabei bedenken, dass es beim Dimmen von LEDs relativ egal ist, ob sie über einen Zyklus am Stück an sind, oder ob sie zwischendurch ausgeschaltet werden - wichtig ist unterm Strich nur, wie viel sie im im Laufe eines Zyklus aktiv sind. Bei einer Auflösung von b bit gibt es bei dieser Methode b Zeitpunkte - ganz egal wie viele Kanäle man verwendet und: deren Timing ist fest. Zudem sind diese sind zeitlich immer mit Faktor 2 voneinander getrennt. Nun schaltet man den Kanal immer dann an, wenn im Helligkeitswert das "Bit" des zugehörigen Zeitschlitzes aktiv ist. Da es visuell deutlich besser als mit Text funktioniert, hier mal zwei Beispiele mit einer Modulation mit 3 Bit. Die Wertigkeit steht links, die An-Zeiten entsprechen den grünen Blöcken (deren X-Achse der Zeit entspricht) und die nötigen Interrupts sind mit roten Pfeilen markiert: <gallery> anykeyx6_pwm.png | Pulsweitenmodulation anykeyx6_plm.png | Pulsleistungsmodulation </gallery> Betrachtet man die aktive Fläche der einzelnen Helligkeitswerte, kommt man auf das gleiche - nur dass die PDM deutlich ressourcenschonender ist. Dazu kommt der Effekt, dass durch das "Zerhacken" der PWM die LEDs mit einer höheren Frequenz flackern (auch wenn sie variiert). Dadurch wird der Stroboskop-Effekt verringert - des einen Freud ist des anderen Leid: achtet man auf EMV, wird es and er Stelle unangenehmer. Aber genug dazu. Aufgrund des Multiplexing gibt es, wie oben beschrieben, nur ein Drittel an Helligkeit. Die meisten LEDs halten bei pulsförmiger Ansteuerung deutlich mehr Strom als im Dauerbetrieb aus weil der limitierende Faktor die Erwärmung ist. Da die LEDs (im 5050-Gehäuse) für den Aufbau von einem LED-Streifen "geerntet" wurden, habe ich kein Datenblatt zur Komponente, aber Wissen: z. B. kommt für den roten Strang ein 330 Ohm-Widerstand zum Einsatz, bei 12 V und 3 roten LEDs in Reihe mit ca. 1,85 V Vorwärtsspannung sind das etwa 20 mA. Ohne weitere Infos zu maximalen Strömen und weil die Helligkeit eigentlich reichen sollte, bin ich bei diesem Strom geblieben. ==Taster== Die Taster kommen direkt an IOs und sind gegen Masse verschaltet. Eine rudimentäre Entprellung wird in Software gemacht. ==USB== Die USB-Beschaltung entspricht weitestgehend der aus den Beispielen von Objective Development. Aus reiner Faulheit habe ich die Schutzbeschaltung vom [[USB-Fußtaster]] übernommen. Sprichwörtlich: Die nötigen Bauteile bestückt und die Leiterkarte auf die passende Größe gestutzt. ==Schaltplan== Die gesamte Schaltung ist also relativ einfach. Als FETs für die LEDs kommen BSS84 (p-Kanal, aufseiten der Anoden) und BSS138 (n-Kanal, aufseiten der Kathoden) zum Einsatz. Aufgrund der Komplexität reicht es als Handskizze: <gallery> anykeyx6_sch.png | Schaltplan - unbekannter Künstler, 2020, digital </gallery> =Firmware= Die Firmware ist erstaunlich einfach, zumal ich mich nicht sonderlich bemüht habe. Die LEDs werden mit der oben beschriebenen Methode (in leddrv.c) angesteuert, wobei zusätzlich noch eine Fading-Funktion zum Einsatz kommt. Das entlastet den USB-Stack und verringert das Flackern (siehe weiter unten) Die Tasten werden (sofern die PWM nicht höhere Priorität hat) jede Millisekunde abgefragt (<code>buttons_tick()</code>) und wenn der Pegel low (Taste gedrückt) ist, ein Zähler inkrementiert. Bei High-Pegel wird der Zähler auf 0 zurückgesetzt. Ist der Zähler größer als 10, gilt die entsprechende Taste gedrückt. Alle Buttons in einem Byte können über die Methode <code>buttons_values()</code> abgefragt werden. In Sachen USB wird ein Out-Report (PC -> Device) mit Netto 16 Byte und ein In-Report mit Netto 8 Byte (Device -> PC) verwendet. Der Out-Report dient zum Setzen der LEDs und sieht wie folgt aus: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index der LED (1-6) * <span class="hb2">Rx</span>: Rot-Wert der LED (0 ... 255) * <span class="hb3">Gx</span>: Grün-Wert der LED (0 ... 255) * <span class="hb4">Bx</span>: Blau-Wert der LED (0 ... 255) * <span class="hb5">Tx</span>: Dauer für den Übergang (0 ... 255, in 5 ms-Schritten) Es können somit 3 Farben gleichzeitig geschrieben werden, Index 0 wird nicht verwendet, da es üblicherweise der Init-Wert für Arrays ist und somit nicht versehentlich die Farbe einer Taste gesetzt wird. Der In-Report ist denkbar einfach, im ersten Byte steht das Bit-Muster der aktuell gedrückten Taster: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> Der Report wird bei jeder Änderung des Zustands der Taster gesendet. Das ist in mehrerlei Hinsicht nicht ganz ideal, da zum einen der Initiale Zustand (nach Öffnen des Devices) nicht ermittelt werden kann und falls doch mal ein USB-Paket verloren geht, verpasst man Tastendrücke. Aber: es musste schnell gehen. =Mechanik= Die Mechanik ist (zumindest für mich als Neuling in Sachen Design und 3D-Druck) ein Stück aufwändiger. Einfach nur die Leiterkarte auf den Tisch zu knallen geht hier nicht, es muss nicht wie aus dem Ei gepellt aussehen, aber nicht nur aus der Kategorie "form follows function" sein. Um schnell voran zu kommen, kam das MS Paint im 3D-Design zum Einsatz: SketchUp. Mit allen Einschränkungen und fehlender Parametrisierung bin ich darin leider noch immer am schnellsten, etwas für den Druck vorzubereiten. ==Tasten== Mit ein bisschen Zeichnen in 2D-Software stellte sich heraus, dass rechteckige Tasten mit 15 mm Breite und Höhe, einer Abrundung mit Radius 2,5 mm und einem Abstand von 5 mm zueinander eine angenehme Haptik aufweisen. Ein erstes Muster mit Kragen (damit die Taste nicht durchs Gehäuse fällt) aus transparentem PLA, (wenn ich mich richtig erinnere) 50 % Infill und konzentrischem Top/Bottom-Pattern (in Cura gesliced) ist schnell gedruckt und sieht, nachdem es mit Farbe beschmiert wurde um zu sehen wie dicht der Druck ist, auch nach dem Reinigen versaut aus. Licht geht durch, sieht aber eher bescheiden aus: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Ausleuchtung bei konzentrischem Druck </gallery> Als nächstes kommt die Frage: wie die LEDs und Taster montieren? um das mechanische Design zu vereinfachen, habe ich die Idee verfolgt, möglichst Gleichteile zu verwenden. In meinen letzten Leiterkarten-Bestellungen habe ich im Waste immer 1x1 mm Kupferflächen im 1,27 mm-Raster platziert, ein Streifen damit ist etwa 9,6 mm breit (bei 1,6 mm Materialdicke) - eine gute Größe für diese Anwendung. LED auf die eine Seite, Taster auf die andere und eine Idee, für die mich die Mechaniker in der Arbeit (völlig zu Recht) vermutlich nicht mehr anschauen würden: Constraining auf zwei Bezugsebenen. Normalerweise strebt man an, dass sich die Toleranzen von einer Seite aus ausbreiten, damit man die Toleranzketten in Griff halten kann. Würde hier heißen: Die Tasten sind auf die Gehäusefront referenziert und dementsprechend müssen die Taster auch an einer Ebene montiert werden, deren Toleranz sich auf die Front bezieht. Bei mir sollen die Taster aber gegen die Bodenplatte drücken. Mit vielen Nachteilen. Da es sich aktuell allerdings um ein Einzelstück handelt: Egal. Das Platinchen mit LED vorne und Taster hinten wird einfach in eine Nut im Taster eingeschoben. Bis auf einen kleinen (reproduzierbaren) Druckfehler funktioniert das prächtig. Hier die verschiedenen Designiterationen: <gallery> anykeyx6_taste_iterationen.jpg | Iterationen der Tasten 1 bis 5.5 anykeyx6_sketchup_taste_seite.png | Finales Modell der Tasten von der Seite anykeyx6_sketchup_taster_unten.png | und von unten anykeyx6_taste_einzelteile.jpg | Einzelteile der Tasten (der Taster fehlt) anykeyx6_taste_LED.jpg | Leiterkarte in die Taste eingeschoben </gallery> Mit Infill auf 100 % und der Tasterfront auf dem Druckbett entsteht eine relativ schöne Oberfläche. Da Concentric Top/Bottom-Pattern ein Kreuz in der Diagonale erzeugt hat, bin ich auf "Lines" umgestiegen, das die Taster, gemeinsam mit dem konzentrischen Rahmen fast schon "wie gekauft" aussehen lässt. Um eine bessere Farbmischung zu erzeugen (und die Taster eine eigenwillige Streuwirkung haben), habe ich etwas Band aus meinem Beschriftungsgerät (Wenn es wichtig ist: Brother P-touch) hinter den Taster geklebt. Dadurch wird die Ausleuchtung der drei LED-Kristalle zumindest ein bisschen homogener: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Zum Vergleich nochmal das Bild von oben (konzentrischer Druck) anykeyx6_beleuchtung_diffusor.jpg | links ohne Folie, rechts mit </gallery> Insgesamt hat das Sandwich eine Höhe von 12,4 mm - 0,25 mm weniger, wenn der Taster gedrückt ist. Der Kragen ist 2,5 mm nach innen versetzt. Das, plus die Dicke der Gehäuseteile, wird die Gesamtdicke des Geräts. =Gehäuse= Mit den Maßen der Tasten geht es los, wobei die Ausschnitte für diese um 0,25 mm in alle Richtungen erweitert wurden. Das bringt zwar etwas Spiel, aber bevor der Cutter angesetzt oder nochmals gedruckt werden muss, dürfen die Tasten eher ein bisschen wackeln - zumal es bei den ersten Tastern ordentlich Elefantenfüße gab. Mit einem Überstand von 7,5 mm von der Kante der Taster zu den Gehäusewänden in drei Richtungen und etwas mehr (17,5 mm) in die vierte Richtung - irgendwo muss ja die Elektronik hin - ist das Gehäuse relativ kompakt. Im inneren befinden sich zwischen den Tastern 4 mm hohe Wände - nicht zum Ausrichten, sondern vielmehr um Streulicht zwischen den Tastern zu vermeiden. Damit sich das Gehäuse nicht durchbiegt und dadurch versehentlich mehrere Taster auf einmal betätigt werden, befinden sich in den Kreuzungspunkten der Taster Erhöhungen, die die Stabilität in Z-Richtung erhöhen. Um Material und vor allem Druckzeit zu sparen, gab es zwei abgeschnittene Druckmuster, die man dank transparentem Filament auf weißem Grund fast nicht sieht: <gallery> anykeyx6_druckmuster_deckel.jpg | Druckmuster für die Aufnahme der Tasten </gallery> Als Zugentlastung des fest installierten USB-Kabels befindet sich hinter dem U-förmigen Ausschnitt eine kleine Rampe und ein Loch, durch den ein Kabelbinder passt. Die Rampe dient lediglich dazu, dass der Kabelbinder die untere Gehäusehälfte nicht nach unten drückt. Man könnte mutmaßen, dass durch die Druckschichten bedingte Treppenstruktur die Leitung sogar ein bisschen verhakt wird. 3 Löcher, durch die M2,5-Schrauben passen, dienen zur Befestigung der Bodenplatte. Insgesamt gab es 4 Iterationen, wobei nur zwei den Weg auf den Drucker gefunden haben - und das auch nur, weil sich das erste Druckteil vom Druckbett abgelöst und dadurch unschön verzogen hat. Anscheinend sind die STL-Daten nicht ganz sauber, wodurch das Modell wohl etwas in der Luft hängt. Durch einen Microstep von -0,001 in Z-Richtung wurde das Druckergebnis besser, aber die erste Lage ist trotzdem noch etwas lückig... <gallery> anykeyx6_sketchup_deckel.png | 3D-Modell des Deckels anykeyx6_deckel_vergurkt.jpg | Der erste Versuch (vergurkt) anykeyx6_Deckel.jpg | Der bessere Druck. </gallery> Das untere Gehäuseteil sind eigentlich 7 Teile und brauchte keine Revision (aber einen kleinen Eingriff mit dem Skalpell). Die Komplexität ist auch deutlich geringer. Auffallend sind zunächst die 4 "Kamine" - die Idee dahinter ist, Muttern einzulegen und diese mit dem oberen Gehäuseteil zu verschrauben. Das ganze ist (eher unbeabsichtigt) auf Pressung designed, sowohl für die Mutter, als auch in Richtung anderes Gehäuseteil. Immerhin rutscht nichts. An den Positionen der Taster befinden sich Sacklöcher/Kerben - aus einem sehr einfachen Grund: Material und Druckzeit sparen. Die Bodenplatte soll in weiten Teilen dick genug sein, dass sie stabil ist aber auf keinen Fall ein zweites Mal gedruckt werden muss. Um die Taster in der Höhe einzupassen, werden kleine Distanznippel eingesetzt, die klein sind und dadurch sehr schnell angepasst und gedruckt werden können. Weil ich keinen Sekundenkleber mehr da hatte, sind sie lediglich einseitig auf der Bodenplatte mit doppelseitigem Klebeband befestigt. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D-Modell der Bodenplatte anykeyx6_shim.png | Das 3D-Modell eines Nippel anykeyx6_bodenplatte_benippelt.jpg | Bodenplatte mit Muttern und Nippeln </gallery> Insgesamt war der Drucker etwa 4 Stunden beschäftigt, wobei er auch nicht mit maximaler Geschwindigkeit lief. Die Materialkosten liegen (ohne Probestücke und Fehldrucke) bei etwa 50 cent wenn ich mich nicht täusche, also nicht wirklich der Rede wert. =Zusammenbau= Ursprünglich habe ich einen Atmega8 im DIP-Gehäuse vorgesehen. Da es aber doch ein bisschen eng geworden wäre, kam dann doch einer im TQFP-Gehäuse zum Einsatz. Neben dem Mikrocontroller finden auch die 9 Transistoren für die LED-Ansteuerung Platz auf der Selfmade-Punktrasterplatine: <gallery> anykeyx6_platine.jpg | Bestückte Leiterkarte. </gallery> Die LED-Tasten bekommen gehörig lange Anschlussleitungen aus Kupferlackdraht, die durchgepiepst und auf passend beschriftete Klebebandstreifen landen. Miteinander verdrillt und verlötet kommen sie dann an die FETs. Gleiches Spiel für die Massen der Taster. <gallery> anykeyx6_tastenverdrahtung.jpg | Etwas Ordnung im Chaos </gallery> Damit die Tasten beim Zusammenfügen nicht immer wieder aus ihren Löchern entwischen, kommt Klebeband von außen auf das Gehäuse. Zur Sicherheit mit Nummern beschriftet, damit mit Drehen und Spiegeln nix schief geht. Tasten eingelegt, Leitungen im Gehäuse verlegt und den Kupfer-Knäuel zusammengedrückt. Papa sagte schon immer: Salat ist gesund. Das USB-Kabel liegt fest verzurrt und sehr engem Biegeradius im Gehäuse - hält (hoffentlich). <gallery> anykeyx6_boden_und_deckel.jpg | Beide Gehäusehälften anykeyx6_deckel_verklebt.jpg | Bestückungshilfe anykeyx6_deckel_assy.jpg | Deckel mit eingelegten Komponenten </gallery> In die untere Gehäusehälfte sind die Nippel schon eingeklebt und es wird spannend: passt es? Leider sind keine Senkkopfschrauben im Haus, also bleibt es mit den verzinkten Zylinderkopf-Schrauben etwas hässlich. Oder pragmatisch. Naja, es hält - und die Tasten liegen so im Gehäuse, dass sie weder (allzu sehr) klappern noch permanent gedrückt werden. Erfolg! :) Um bei den Tasten nicht im kompletten Blindflug zu sein, ziert noch ein Label und ein paar Symbole der FontAwesome die obere Reihe. Damit sollte nun nichts mehr schief geben. =Software= ==Erster Test== Die erste Testsoftware ist in Python geschrieben und lässt einen Regenbogen durchlaufen. Der Einfachheit halber fasst sie nur eine LED gleichzeitig an: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> Sieht dann als Momentaufnahme in etwa wie folgt aus: <gallery> anykeyx6_rgb_demo.jpg | Farben, yay! </gallery> ==Der OBS-Client== Ein "echtes" Plugin für OSB Studio zu schreiben spare ich mir mangels Tiefe in C++. Stattdessen nutze ich [https://github.com/Palakis/obs-websocket obs-websocket], das eine API für C# anbietet, die extrem einfach zu bedienen ist. Für die Buttons ist eine extrem rudimentäre Klasse sehr schnell zusammengehackt. Gänzlich ohne Fehlerbehandlung. Das Auslesen der Buttons erfolgt in einem Background-Worker, der Events feuert (und beim Loslassen zusätzlich die Dauer des Drückens ermittelt), das Setzen der LED-Farben erfolgt für alle 6. Hier merkt man auch wie heiß die Nadel ist mit der gestrickt wird: Zwischen dem Schreiben der beiden "Sets" legt sich die Software für eine Millisekunde schlafen. Der Grund einst einfach die dämlich - schreibt man zu schnell, geht evtl. das erste der beiden Datenpakete in der Firmware verloren, weil die Übergabe nicht (wenn man es so nennen will) threadsafe ist. Die GUI hat lediglich einen "Connect"-Button, der nur gedrückt werden sollte, wenn OBS läuft und die Hardware verbunden ist. Die Konfiguration ist ebenfalls eher grundlegend und in AnykeyOBS.exe.config zu finden. Hier kann für jede Taste die Aktiv/Inaktiv-Farbe als Hex-Code (oder named color, ungetestet) abgelegt werden, die Funktion definiert und ein Argument für diese Funktion angegeben werden. Zum Zuordnen einer Szene packt man in die Funktion "Scene" und schreibt den zugehörigen Szenen-Namen ins Argument. Für die Aufnahme heißt die Funktion "Record" und als Argument kann "Toggle", "Start" und "Stop" definiert werden. Streaming wird noch nicht unterstützt. Aus mir nicht ganz verständlichen Gründen kann der Zustand des Streamings/Recordings nur über Events ermittelt werden, dadurch bleibt die Taste mit entsprechender Zuordnung beim Start des Programms orange. Dies ist auch die (fest hinterlegte) Farbe für Übergänge zwischen Aufnahme und keine Aufnahme. Ein weiteres Feature ist das Abbrechen einer Funktion - Grundsätzlich werden die Aktionen erst beim Loslassen des Tasters getriggert - außer man drückt diesen länger als eine Sekunde. In diesem Fall wird die Aktion abgebrochen. Insgesamt kann man die Software allerhöchstens als Proof of Concept bezeichnen. Es funktioniert, irgendwie. ===Feuerprobe=== Mittlerweile durfte ich meine Schwester sogar besuchen, um ihr die Hardware zu geben. yay! Das Einrichten fand aber trotzdem online statt. obs-websockt installiert, AnykeyOBS aufs Tablet und: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Mist. Die vermutliche Ursache ist schnell gefunden: Bei manchen USB-Geräten kann der Name nicht gelesen werden. Eine Packung try-catch auf das Problem geworfen und eine Prise <code>Console.WriteLine</code>s und das Programm bleib nach dem Klick auf "Connect" geöffnet. "Leuchten die Knöppe?" - "Oh mann, wie geil" - "Also ja?". Danach hörte ich nur noch wildes Klicken. Ich glaube, das Teil gefällt. Und so sieht es aus: [[Datei:anykeyx6_demo.mp4|500px]] =Fazit= Wo fange ich an? Beim Guten, beim Schlechten oder bei den Sachen, für die ich mich schäme? Unterm Strich: für eine sehr hemdsärmelig zusammengestrickte Hardware sieht es (ohne dass ich mich selbst loben möchte) ganz ordentlich aus. Schlimm wird es erst, wenn man unter die Haube schaut. Das dafür aber auch konsequent. Das Gute: * Meine Schwester hat etwas, das ihr hoffentlich die Arbeit etwas erleichtert * Ich habe wieder einiges in Sachen 3D-Druck gelernt * Es hat ziemlich viel Spaß gemacht * Alles ist bunt Das Schlechte: * Decoupling, welches Decoupling? * LEDs ** Nicht sonderlich hell ** Flackern bei USB-Traffic (durch INT0) ** In dunkler Umgebung zu hell und bei Tageslicht schlecht sichtbar * Das Setzen von LEDs und Tastendrücke können verschluckt werden * Taster ** Können auch von der Gehäuseunterseite betätigt werden ** Relativ laut (im Video hörbar) ** Wackeln, sind schief und haben keine Führung * Software ** An allen Ecken und Enden rudimentär, wenn etwas ausfällt, funktioniert erst einmal nichts ** Kein automatisches Verbinden mit OBS und der Hardware ** Keine GUI für die Konfiguration ** So gut wie keine Funktionen in OBS unterstützt ** Außer OBS-Steuerung keine weiteren Funktionen * Keine Standby-States =Downloads= * [[Datei:Anykeyx6.zip]] SketchUp-Dateien, zugehörige STLs, Firmware und C#-Software um mit OBS zu sprechen. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] 6edd6587320c29848548f4c4ad99b185e1828a4d Anykey x6/en 0 703 1591 1589 2020-05-11T18:49:09Z Chris 2 /* First fire */ now with a video player wikitext text/x-wiki ''This is an translation of [[Anykey x6]], mostly done with the free version of deepl.com and some proofreading.'' [[Datei:anykeyx6_komplett.jpg|thumb|Completely assembled hardware (colors slightly retouched)]] My sister is a teacher. A job I don't envy her for - especially in 2020. Here in Bavaria life at school is slowly starting again (as of the beginning of May), but in parallel to the classes in the schools the children who stay at home have to be taught as well. If you take your own work seriously, this is no fun. Sure, you could simply throw worksheets over the fence and refer to pages in the textbooks, but when I think of my own school days and the rather extrinsic motivation... Although my sister has a lot of digital material, teaching (especially languages) needs someone who speaks in front of the class and of course independent learning isn't easy for everyone. That's why she started making videos. At first only with printed sheets and the mobile phone on the tripod. To be able to use her digital materials better, she asked for a screen recorder. [https://obsproject.com/ OBS] was quickly installed and set up. Too bad she doesn't have a second monitor (or display port adapter) for her MS Surface. So that her students can see her (or even do "blackboard lessons"), I created several scenes in OBS: * Screen recording * Screen recording + camera in the corner * Camera The only stupid thing is that without that second screen she has to bring OBS to the foreground for every action. You could also create global hotkeys, but without a full keyboard you run the risk of getting double assignments and thus have very strange behaviour on the PC. At the same time you don't see what OBS is actually doing. Yes, you can install a remote control for OBS on your tablet or smartphone, but this only creates more problems than it solves, especially since you have to reconfigure the (free) clients I found right away for each session. Furthermore the device has to stay on and there are no physical buttons to feel. This is unnecessarily distracting and does not really increase acceptance. Even ready-made solutions like the Elgato Stream Deck are disproportionately expensive for the (hopefully) short period of use. At the same time, there is an engineer sitting around here who, due to the current situation, is reducing flextime. =The idea= How about some tinkering? A few buttons, a few LEDs, a little firmware and a few lines of code on the PC. Why should it be so complex? Well, let's get one thing straight: If you go beyond your objective it's gonna take a lot of work. The goal is to have 6-8 colorfully illuminated buttons that can be integrated into OBS. The microcontroller was easy to select. To be not too far from the code examples of [https://www.obdev.at/products/vusb/index-en.html V-USB], a vintage ATmega8 is the way to go. Since I wanted to do something with intelligent LEDs for a long time, there is a strip with WS2812B lying around way too long. The plan was to glue it - maybe even still on the strip - on push buttons. Of course, the [[wikipedia:Woman acceptance factor|WAF]] must fit somehow, so a not too shabby housing is crucial. Thanks to a 3D printer, I'm able to do this (at least in terms of the equipment). =Electronics= The disillusionment came faster than expected. I knew that the timing of the LEDs is critical. That this also applies to V-USB, too. That it is not so easy to combine the two came clear very quickly. The USB stack absolutely needs a pin interrupt, but to control the LEDs, it must be switched off - otherwise everything flashes like a Christmas tree on LSD. Tim (aka cpldcpu) has taken the effort to enable V-USB with [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling] - even with a corresponding LED. I didn't want to go that way because it could potentially be painful in other places. Ok, what now? A coprocessor that converts UART/I²C to the LED protocol? Actually, I didn't want to build a multiprocessor system - and again, the problem with interrupts vs. no interrupts remains, also due to the limitations of USI, this might be a bit uptight. Good advice is expensive. But I didn't want to go back to single-color LEDs either. ==LED driver== To control 6 RGB LEDs with PWM, 18 PWM channels are required. I don't think any AVR8 supports that. I have a PCA9685 lying around, providing only 16 channels. In addition the component with its breakout board takes quite a lot of space. Too much for what I have in mind. Have I written 18 channels? Yes and no. When multiplexing, between 3 and 6 are sufficient. Finally, I decided to take the colors into multiplex and let the PWM run per key - with corresponding losses of brightness (one third). But where do you get 6 synchronous PWM channels on an ATmega8? Very simple: not at all. At least in hardware - it looks different in software, where it's not a real PWM, but rather a pulse power modulation (short PPM - I could find a suitable term, hence the new creation, not to confuse with parts per million or pulse-position modulation, the German abbreviation works a little better), as it was already described in 2011 on the German [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite]. To describe it briefly: with normal PWM there are two switching points for each channel, one of which is individual for each channel (because it determines the brightness value). If you have n channels, there are n points in time which you have to hit as accurately as possible. Especially if they are close together, this can lead to timing problems. The dimmer used here works differently. You have to keep in mind that when dimming LEDs, it doesn't matter if they are on for a cycle at a time or if they are switched off in between - important is how much they are active during a cycle. With a resolution of b bit, this method gives you b points in time - no matter how many channels you use and: their timing is fixed. In addition, they are always separated in time by a factor of 2. Now the channel is always switched on when the "bit" of the corresponding time slot is active in the brightness value. Since the explanation works much better visually than with text, here are two examples with a 3 bit modulation. The valence is on the left, the on times correspond to the green blocks (whose x-axis corresponds to the time) and the necessary interrupts are marked with red arrows: <gallery> anykeyx6_pwm.png | Pulse width modulation anykeyx6_plm.png | Pulse power modulation </gallery> If you look at the active area of the individual brightness values, you come to the same total area - only that the PPM has a significantly higher efficiency. In addition, there is the effect that by "chopping" the PWM, the LEDs flicker at a higher frequency (even if it varies). This reduces the stroboscopic effect - one person's joy is another's misfortune: considering EMC it becomes more uncomfortable at that point. But enough about that. Due to multiplexing, there is, as described above, only a third of the brightness. Most LEDs can handle much more current when driven with pulses than in continuous operation because the limiting factor is heat. Since the LEDs (in the 5050 package) were "harvested" from a LED strip for the assembly, I don't have a datasheet for them, but knowledge: e.g. a 330 Ohm resistor is used for the red strand, with 12 V and 3 red LEDs in series with approx. 1.85 V forward voltage each this is about 20 mA. Without further information about maximum currents and because the brightness should be enough, I stayed with this current. ==Switches== The buttons are connected directly to IOs and are wired to ground. A rudimentary debouncing is done in software. ==USB== The USB circuitry corresponds as far as possible to the examples from Objective Development. Out of sheer laziness I took over the protection circuitry from the [[USB-Fußtaster|USB foot switch]]. Proverbially: I assembled the necessary components and trimmed the circuit board to the right size. ==Circuit diagram== So the whole circuit is relatively simple. The FETs for the LEDs are BSS84 (p-channel, on the anode side) and BSS138 (n-channel, on the cathode side). Because of the simplicity a hand sketch does the job: <gallery> anykeyx6_sch.png | schematic - unknown artist, 2020, digital </gallery> =Firmware= The firmware is surprisingly simple, especially since I didn't try very hard. The LEDs are controlled with the method described above (in leddrv.c), with an additional fading function. This relieves the USB stack and reduces flickering (see below) The keys are polled (unless PWM has higher priority) every millisecond (<code>buttons_tick()</code>). In case the level is low (key pressed), a counter is incremented. If the level is high, the counter is reset to 0. If the counter is greater than 10, the corresponding key is considered pressed. All buttons in one byte can be queried via the method <code>buttons_values()</code>. As far as USB is concerned, an Out-Report (PC -> Device) with net 16 bytes and an In-Report with net 8 bytes (Device -> PC) is used. The Out-Report is used to set the LEDs and looks as follows: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index of the LED (1-6) * <span class="hb2">Rx</span>: Red value of the LED (0 ... 255) * <span class="hb3">Gx</span>: Green value of the LED (0 ... 255) * <span class="hb4">Bx</span>: Blue value of the LED (0 ... 255) * <span class="hb5">Tx</span>: Duration for the transition (0 ... 255, in 5 ms steps) This way, colors for 3 buttons can be written at once, index 0 is not used, because it is usually the init value for arrays and therefore the color of a key is not set by mistake. The in-report is very simple, the first byte contains the bit pattern of the currently pressed buttons: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> The report is sent every time the status of the buttons changes. This is not quite ideal in several respects, because on the one hand the initial state (after opening the device) cannot be determined and on the other hand, if a USB packet is lost, you miss keystrokes. But: it had to be implemented quickly. == Mechanics== The mechanics are (at least for me as a noob to design and 3D printing) a bit more complex. Just banging the circuit board on the table is not possible here, it doesn't have to look spick and span, but it shouldn't completely be "form follows function". To get ahead quickly, the MS Paint in 3D design was used: SketchUp. With all the limitations and lack of parameterization, it's still the fastest way for me to prepare something for printing. ==Keys== With a little drawing in 2D software, it turned out that rectangular keys with a width and height of 15 mm, a rounding with a radius of 2.5 mm and a distance of 5 mm to each other have a pleasant look & feel. A first pattern with a collar (so the key doesn't fall through the case) with transparent PLA, (if I remember correctly) 50 % infill and concentric top/bottom pattern (sliced in Cura) is printed quickly and looks, after being smeared with ink to see how tight the print is, dirty even after cleaning. Light goes through, but looks rather modest: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Illumination with concentric printing pattern </gallery> Next comes the question: how to assemble the LEDs and switches? to simplify the mechanics, I followed the idea of using common parts where possible. In my last PCB orders I always placed 1x1 mm copper areas in the waste in a 1.27 mm grid, a strip with this is about 9.6 mm wide (with 1.6 mm material thickness) - a good size for this application. LED on one side, buttons on the other and an idea for which the designers at work would probably (quite rightly) not look at me anymore: Constraining on two reference planes. Normally, you aim to have the tolerances spread out from one side so that you can keep the tolerance chains under control. Would mean here: The keys are referenced to the front of the case and accordingly, the keys have to be mounted on a plane whose tolerance refers to the front. But in my case the keys should press against the base plate. With many disadvantages. Since it is currently however a single piece: No matter. The PCB with LED in the front and switch in the back is simply inserted into a groove in the button. Except for a small (reproducible) printing error, this works perfectly. Here are the different design iterations: <gallery. anykeyx6_taste_iterationen.jpg | iterations of keys 1 to 5.5 anykeyx6_sketchup_taste_seite.png | Final model of the keys from the side anykeyx6_sketchup_taster_unten.png | and from below anykeyx6_taste_einzelteile.jpg | individual parts of the keys (w/o switch) anykeyx6_taste_LED.jpg | circuit board inserted into the button </gallery> With infill set to 100 % and the button front on the printing bed, a relatively nice surface is created. Since Concentric Top/Bottom-Pattern created a cross in the diagonal, I switched to "Lines", which, together with the concentric frame, makes the push buttons look almost "like a bought one". In order to achieve better color mixing (and the buttons have a strange scattering effect), I glued some tape from my label printer (if it is important: Brother P-touch) behind the button. This makes the illumination of the three LED crystals at least a bit more homogeneous: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | For comparison again the picture from above (concentric printing pattern) anykeyx6_beleuchtung_diffusor.jpg | left without, right with tape </gallery> In total the sandwich has a height of 12.4 mm - 0.25 mm less when the button is pressed. The collar is offset 2.5 mm to the inside. This, plus the thickness of the case parts, becomes the total thickness of the device. =Housing= The dimensions of the buttons are the starting point, with the cut-outs for them extended by 0.25 mm in all directions. This brings some play, but before the cutter has to be attached or printed again, the keys may wobble a little - especially since there were some elephant feet in the first keys. With a projection of 7.5 mm from the edge of the buttons to the case walls in three directions and a little more (17.5 mm) in the fourth direction - the electronics have to go somewhere - the case is relatively compact. Inside, there are 4 mm high walls between the buttons - not for alignment, but rather to avoid stray light between the buttons. To prevent the housing from bending and thus accidentally actuating several buttons at once, there are elevations in the crossing points of the buttons which increase stability in the Z-direction. To save material and especially printing time, there were two cut-off test prints, which are almost invisible on a white background on white background thanks to the transparent filament: <gallery> anykeyx6_druckmuster_deckel.jpg | Print pattern for the keys </gallery> As strain relief for the permanently installed USB cable, there is a small ramp behind the U-shaped cut-out and a hole through for a cable tie. The ramp only serves to prevent the cable tie from pressing down the lower half of the housing. One could speculate that the stair structure caused by the print layers might even help the cable to not slip out. 3 holes, through which M2.5 screws fit, are used to hold everything together. There were 4 iterations in total, but only two of them found their way to the printer - and that only because the first part lifted off the printing bed and thus was warped. Apparently the STL data is not quite clean, so the model is probably a bit hanging in the air. With a microstep of -0.001 in the Z-direction, the printing result was better, but the first layer is still a bit grubby... <gallery> anykeyx6_sketchup_deckel.png | 3D model of the upper shell anykeyx6_deckel_vergurkt.jpg | The first try (warped) anykeyx6_Deckel.jpg | The better print. </gallery> The lower part of the case is actually 7 parts and needed no revision (but a small operation with the scalpel). The complexity is also much lower. The 4 "chimneys" are striking at first - the idea behind them is to insert nuts and screw them to the upper part of the case. The whole thing is (rather unintentionally) designed for compression, both for the nut and towards the other part of the housing. At least nothing slips. There are blind holes/indents at the positions of the buttons - for a very simple reason: save material and print time. The base plate should be thick enough to be stable but not to have to be printed a second time. In order to fit the buttons in height, small spacer nipples are used, which are small and therefore can be adjusted and printed very quickly. Because I didn't have any super glue left, they are only fixed on one side on the base plate with double sided adhesive tape. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D model of the bottom plate anykeyx6_shim.png | The 3D model of a nipple anykeyx6_bodenplatte_benippelt.jpg | Floor plate with nuts and nipples (and I thought this was bad in German) </gallery> All in all, the printer was busy for about 4 hours, although it was not running at maximum speed. The material costs are (without samples and misprints) about 50 cent if I am not mistaken, so not really worth mentioning. =Assembly= Originally I planned to use an Atmega8 in a DIP package. But since it would have been a bit tight, I decided to use one in a TQFP package. Besides the microcontroller, the 9 transistors for LED control are also located on the self-made dot matrix board: <gallery> anykeyx6_platine.jpg | Assembled circuit board </gallery> The LED keys are fitted with long connecting leads made of enamelled copper wire, which are beeped through and stuck on correspondingly labelled tape strips. Twisted and soldered together, they then are connected the FETs. Same procedure for the ground of the switches. <gallery> anykeyx6_tastenverdrahtung.jpg | Tidying up the chaos </gallery> To prevent the keys from repeatedly slipping out of their holes when the housing is closed, tape is applied to the outside of the case. For safety reasons, it is labeled with numbers so that nothing can go wrong with turning and mirroring. Keys inserted, cables laid in the case and the copper ball is formed. Cable spaghetti, anyone? The USB cable is firmly lashed down and has a very tight bending radius in the case - it's in (hopefully). <gallery> anykeyx6_boden_und_deckel.jpg | both halves of the housing anykeyx6_deckel_verklebt.jpg | some assembly aid anykeyx6_deckel_assy.jpg | lid with inserted components </gallery> The nipples are already glued into the lower half of the housing and it gets exciting: does it fit? Unfortunately there are no countersunk screws in the part box, so it remains a bit ugly with the galvanized cylinder head screws. Or pragmatic. Well, it holds - and the buttons are in the case in such a way that they neither (too much) rattle nor are they pressed permanently. Success! :) To give the buttons some more meaning, the upper row is decorated with a label of some symbols from FontAwesome. Now nothing should go wrong. =Software= ==first test== The first test software is written in Python and lets a rainbow run through. For the sake of simplicity, it only changes one LED at a time: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> As a snapshot, it looks something like this: <gallery> anykeyx6_rgb_demo.jpg | colors, yay! </gallery> ==The OBS Client== Due to the lack of deep knowledge in C++, I don't even try to write a real plugin for OBS. Instead I use [https://github.com/Palakis/obs-websocket obs-websocket], which provides an API for C# that is extremely easy to use. For the buttons, an extremely rudimentary class is hacked together. No error handling at all. The buttons are read out in a background worker that fires events (and also determines the duration of the press when released), the LED colors are set for all 6 buttons in one method. Here you can also see how hastily cobbled together it is: Between writing the two "sets" of color, the software sleeps for a millisecond. The reason is both simply and stupid: if you write too fast, the first of the two data packets may be lost in the firmware, because the transfer is not (if you want to call it that) threadsafe. The GUI only has a "Connect" button that should only be pressed when OBS is running and the hardware is connected. The configuration is also rather basic and can be found in AnykeyOBS.exe.config Here you can store the active/inactive colors for each button as hex code (or named color, untested), define the function and give an argument for this function. To assign a scene, pack into the function "Scene" and write the corresponding scene name into the argument. For recording, the function is called "Record" and the argument can be defined as "Toggle", "Start" and "Stop". Streaming is not yet supported. For reasons not quite understandable to me, the state of streaming/recording can only be determined by events. Therefore, the key with the corresponding assignment remains orange when the program is started. This is also the (hard coded) color for transitions between recording and no recording. Another feature is the cancelling of actions - basically they are only triggered when the button is released - unless the button is held for more than one second. In this case the action is cancelled. All in all, the software can at best be described as a proof of concept. It works, somehow. ===First fire=== In the meantime I was even allowed to visit my sister to give her the hardware. yay! But the setup was done online, though. Got obs-websocks installed, copied AnykeyOBS on the tablet and: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Shit. The presumed cause is quickly located: Some USB devices' name can't be read. Thrown a pack of try-catch on the problem and a pinch of <code>Console.WriteLine</code>s and the program stays open after clicking "Connect". "Do the buttons light up?" - "Oh man, how cool" - "So yes?" After that I only heard wild clicking. I think she likes it. And this is what it looks like: [[Datei:anykeyx6_demo.mp4|500px]] =Conclusion= Where to start? For the good, the bad or the things I'm ashamed of? Bottom line: for a very shirt-sleeved piece of hardware, it looks (without me wanting to praise myself) quite decent. It only gets bad when you look under the hood. But at least that's pretty consistent. The good: * My sister has something that I hope will make her job a little easier * I've learned a about 3D printing again * It's been a lot of fun * It's quite colorful The bad: * Decoupling, what decoupling? * LEDs ** Not very bright ** Flickering during USB traffic (due to INT0) ** Too bright in dark surroundings and poorly visible in bright daylight * Changes of dropped packets for LED settings and key presses are quite high * Buttons ** Can also be operated from the bottom of the housing ** Relatively loud (can be heard in the video) ** Wobble, are crooked and have no guidance * Software ** Rudimentary in all manners, if anything fails, everything's gone ** No automatic connection to OBS and the hardware ** No GUI for configuration ** Virtually no functions supported in OBS ** No other functions except OBS control * No standby states =Downloads= * [[Datei:Anykeyx6.zip]] SketchUp files, associated STLs, firmware and C# software to talk to OBS. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] [[Kategorie:English translation]] ac1b3cd1d190520f56f565e5a566490f9cd0af4f 1592 1591 2020-05-11T18:49:43Z Chris 2 a/an wikitext text/x-wiki ''This is a translation of [[Anykey x6]], mostly done with the free version of deepl.com and some proofreading.'' [[Datei:anykeyx6_komplett.jpg|thumb|Completely assembled hardware (colors slightly retouched)]] My sister is a teacher. A job I don't envy her for - especially in 2020. Here in Bavaria life at school is slowly starting again (as of the beginning of May), but in parallel to the classes in the schools the children who stay at home have to be taught as well. If you take your own work seriously, this is no fun. Sure, you could simply throw worksheets over the fence and refer to pages in the textbooks, but when I think of my own school days and the rather extrinsic motivation... Although my sister has a lot of digital material, teaching (especially languages) needs someone who speaks in front of the class and of course independent learning isn't easy for everyone. That's why she started making videos. At first only with printed sheets and the mobile phone on the tripod. To be able to use her digital materials better, she asked for a screen recorder. [https://obsproject.com/ OBS] was quickly installed and set up. Too bad she doesn't have a second monitor (or display port adapter) for her MS Surface. So that her students can see her (or even do "blackboard lessons"), I created several scenes in OBS: * Screen recording * Screen recording + camera in the corner * Camera The only stupid thing is that without that second screen she has to bring OBS to the foreground for every action. You could also create global hotkeys, but without a full keyboard you run the risk of getting double assignments and thus have very strange behaviour on the PC. At the same time you don't see what OBS is actually doing. Yes, you can install a remote control for OBS on your tablet or smartphone, but this only creates more problems than it solves, especially since you have to reconfigure the (free) clients I found right away for each session. Furthermore the device has to stay on and there are no physical buttons to feel. This is unnecessarily distracting and does not really increase acceptance. Even ready-made solutions like the Elgato Stream Deck are disproportionately expensive for the (hopefully) short period of use. At the same time, there is an engineer sitting around here who, due to the current situation, is reducing flextime. =The idea= How about some tinkering? A few buttons, a few LEDs, a little firmware and a few lines of code on the PC. Why should it be so complex? Well, let's get one thing straight: If you go beyond your objective it's gonna take a lot of work. The goal is to have 6-8 colorfully illuminated buttons that can be integrated into OBS. The microcontroller was easy to select. To be not too far from the code examples of [https://www.obdev.at/products/vusb/index-en.html V-USB], a vintage ATmega8 is the way to go. Since I wanted to do something with intelligent LEDs for a long time, there is a strip with WS2812B lying around way too long. The plan was to glue it - maybe even still on the strip - on push buttons. Of course, the [[wikipedia:Woman acceptance factor|WAF]] must fit somehow, so a not too shabby housing is crucial. Thanks to a 3D printer, I'm able to do this (at least in terms of the equipment). =Electronics= The disillusionment came faster than expected. I knew that the timing of the LEDs is critical. That this also applies to V-USB, too. That it is not so easy to combine the two came clear very quickly. The USB stack absolutely needs a pin interrupt, but to control the LEDs, it must be switched off - otherwise everything flashes like a Christmas tree on LSD. Tim (aka cpldcpu) has taken the effort to enable V-USB with [https://cpldcpu.wordpress.com/2014/03/19/%c2%b5-wire-usb-on-an-attiny-10/ Polling] - even with a corresponding LED. I didn't want to go that way because it could potentially be painful in other places. Ok, what now? A coprocessor that converts UART/I²C to the LED protocol? Actually, I didn't want to build a multiprocessor system - and again, the problem with interrupts vs. no interrupts remains, also due to the limitations of USI, this might be a bit uptight. Good advice is expensive. But I didn't want to go back to single-color LEDs either. ==LED driver== To control 6 RGB LEDs with PWM, 18 PWM channels are required. I don't think any AVR8 supports that. I have a PCA9685 lying around, providing only 16 channels. In addition the component with its breakout board takes quite a lot of space. Too much for what I have in mind. Have I written 18 channels? Yes and no. When multiplexing, between 3 and 6 are sufficient. Finally, I decided to take the colors into multiplex and let the PWM run per key - with corresponding losses of brightness (one third). But where do you get 6 synchronous PWM channels on an ATmega8? Very simple: not at all. At least in hardware - it looks different in software, where it's not a real PWM, but rather a pulse power modulation (short PPM - I could find a suitable term, hence the new creation, not to confuse with parts per million or pulse-position modulation, the German abbreviation works a little better), as it was already described in 2011 on the German [https://www.schatenseite.de/2011/12/10/i2c-dimmer/ Schatenseite]. To describe it briefly: with normal PWM there are two switching points for each channel, one of which is individual for each channel (because it determines the brightness value). If you have n channels, there are n points in time which you have to hit as accurately as possible. Especially if they are close together, this can lead to timing problems. The dimmer used here works differently. You have to keep in mind that when dimming LEDs, it doesn't matter if they are on for a cycle at a time or if they are switched off in between - important is how much they are active during a cycle. With a resolution of b bit, this method gives you b points in time - no matter how many channels you use and: their timing is fixed. In addition, they are always separated in time by a factor of 2. Now the channel is always switched on when the "bit" of the corresponding time slot is active in the brightness value. Since the explanation works much better visually than with text, here are two examples with a 3 bit modulation. The valence is on the left, the on times correspond to the green blocks (whose x-axis corresponds to the time) and the necessary interrupts are marked with red arrows: <gallery> anykeyx6_pwm.png | Pulse width modulation anykeyx6_plm.png | Pulse power modulation </gallery> If you look at the active area of the individual brightness values, you come to the same total area - only that the PPM has a significantly higher efficiency. In addition, there is the effect that by "chopping" the PWM, the LEDs flicker at a higher frequency (even if it varies). This reduces the stroboscopic effect - one person's joy is another's misfortune: considering EMC it becomes more uncomfortable at that point. But enough about that. Due to multiplexing, there is, as described above, only a third of the brightness. Most LEDs can handle much more current when driven with pulses than in continuous operation because the limiting factor is heat. Since the LEDs (in the 5050 package) were "harvested" from a LED strip for the assembly, I don't have a datasheet for them, but knowledge: e.g. a 330 Ohm resistor is used for the red strand, with 12 V and 3 red LEDs in series with approx. 1.85 V forward voltage each this is about 20 mA. Without further information about maximum currents and because the brightness should be enough, I stayed with this current. ==Switches== The buttons are connected directly to IOs and are wired to ground. A rudimentary debouncing is done in software. ==USB== The USB circuitry corresponds as far as possible to the examples from Objective Development. Out of sheer laziness I took over the protection circuitry from the [[USB-Fußtaster|USB foot switch]]. Proverbially: I assembled the necessary components and trimmed the circuit board to the right size. ==Circuit diagram== So the whole circuit is relatively simple. The FETs for the LEDs are BSS84 (p-channel, on the anode side) and BSS138 (n-channel, on the cathode side). Because of the simplicity a hand sketch does the job: <gallery> anykeyx6_sch.png | schematic - unknown artist, 2020, digital </gallery> =Firmware= The firmware is surprisingly simple, especially since I didn't try very hard. The LEDs are controlled with the method described above (in leddrv.c), with an additional fading function. This relieves the USB stack and reduces flickering (see below) The keys are polled (unless PWM has higher priority) every millisecond (<code>buttons_tick()</code>). In case the level is low (key pressed), a counter is incremented. If the level is high, the counter is reset to 0. If the counter is greater than 10, the corresponding key is considered pressed. All buttons in one byte can be queried via the method <code>buttons_values()</code>. As far as USB is concerned, an Out-Report (PC -> Device) with net 16 bytes and an In-Report with net 8 bytes (Device -> PC) is used. The Out-Report is used to set the LEDs and looks as follows: <code>&gt; <span class="hb1">I0</span> <span class="hb2">R0</span> <span class="hb3">G0</span> <span class="hb4">B0</span> <span class="hb5">T0</span> <span class="hb1">I1</span> <span class="hb2">R1</span> <span class="hb3">G1</span> <span class="hb4">B1</span> <span class="hb5">T1</span> <span class="hb1">I2</span> <span class="hb2">R2</span> <span class="hb3">G2</span> <span class="hb4">B2</span> <span class="hb5">T2</span> xx</code> * <span class="hb1">Ix</span>: Index of the LED (1-6) * <span class="hb2">Rx</span>: Red value of the LED (0 ... 255) * <span class="hb3">Gx</span>: Green value of the LED (0 ... 255) * <span class="hb4">Bx</span>: Blue value of the LED (0 ... 255) * <span class="hb5">Tx</span>: Duration for the transition (0 ... 255, in 5 ms steps) This way, colors for 3 buttons can be written at once, index 0 is not used, because it is usually the init value for arrays and therefore the color of a key is not set by mistake. The in-report is very simple, the first byte contains the bit pattern of the currently pressed buttons: <code>&lt; <span class="hb1">K1</span> xx xx xx xx xx xx xx</code> The report is sent every time the status of the buttons changes. This is not quite ideal in several respects, because on the one hand the initial state (after opening the device) cannot be determined and on the other hand, if a USB packet is lost, you miss keystrokes. But: it had to be implemented quickly. == Mechanics== The mechanics are (at least for me as a noob to design and 3D printing) a bit more complex. Just banging the circuit board on the table is not possible here, it doesn't have to look spick and span, but it shouldn't completely be "form follows function". To get ahead quickly, the MS Paint in 3D design was used: SketchUp. With all the limitations and lack of parameterization, it's still the fastest way for me to prepare something for printing. ==Keys== With a little drawing in 2D software, it turned out that rectangular keys with a width and height of 15 mm, a rounding with a radius of 2.5 mm and a distance of 5 mm to each other have a pleasant look & feel. A first pattern with a collar (so the key doesn't fall through the case) with transparent PLA, (if I remember correctly) 50 % infill and concentric top/bottom pattern (sliced in Cura) is printed quickly and looks, after being smeared with ink to see how tight the print is, dirty even after cleaning. Light goes through, but looks rather modest: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | Illumination with concentric printing pattern </gallery> Next comes the question: how to assemble the LEDs and switches? to simplify the mechanics, I followed the idea of using common parts where possible. In my last PCB orders I always placed 1x1 mm copper areas in the waste in a 1.27 mm grid, a strip with this is about 9.6 mm wide (with 1.6 mm material thickness) - a good size for this application. LED on one side, buttons on the other and an idea for which the designers at work would probably (quite rightly) not look at me anymore: Constraining on two reference planes. Normally, you aim to have the tolerances spread out from one side so that you can keep the tolerance chains under control. Would mean here: The keys are referenced to the front of the case and accordingly, the keys have to be mounted on a plane whose tolerance refers to the front. But in my case the keys should press against the base plate. With many disadvantages. Since it is currently however a single piece: No matter. The PCB with LED in the front and switch in the back is simply inserted into a groove in the button. Except for a small (reproducible) printing error, this works perfectly. Here are the different design iterations: <gallery. anykeyx6_taste_iterationen.jpg | iterations of keys 1 to 5.5 anykeyx6_sketchup_taste_seite.png | Final model of the keys from the side anykeyx6_sketchup_taster_unten.png | and from below anykeyx6_taste_einzelteile.jpg | individual parts of the keys (w/o switch) anykeyx6_taste_LED.jpg | circuit board inserted into the button </gallery> With infill set to 100 % and the button front on the printing bed, a relatively nice surface is created. Since Concentric Top/Bottom-Pattern created a cross in the diagonal, I switched to "Lines", which, together with the concentric frame, makes the push buttons look almost "like a bought one". In order to achieve better color mixing (and the buttons have a strange scattering effect), I glued some tape from my label printer (if it is important: Brother P-touch) behind the button. This makes the illumination of the three LED crystals at least a bit more homogeneous: <gallery> anykeyx6_beleuchtung_konzentrisch.jpg | For comparison again the picture from above (concentric printing pattern) anykeyx6_beleuchtung_diffusor.jpg | left without, right with tape </gallery> In total the sandwich has a height of 12.4 mm - 0.25 mm less when the button is pressed. The collar is offset 2.5 mm to the inside. This, plus the thickness of the case parts, becomes the total thickness of the device. =Housing= The dimensions of the buttons are the starting point, with the cut-outs for them extended by 0.25 mm in all directions. This brings some play, but before the cutter has to be attached or printed again, the keys may wobble a little - especially since there were some elephant feet in the first keys. With a projection of 7.5 mm from the edge of the buttons to the case walls in three directions and a little more (17.5 mm) in the fourth direction - the electronics have to go somewhere - the case is relatively compact. Inside, there are 4 mm high walls between the buttons - not for alignment, but rather to avoid stray light between the buttons. To prevent the housing from bending and thus accidentally actuating several buttons at once, there are elevations in the crossing points of the buttons which increase stability in the Z-direction. To save material and especially printing time, there were two cut-off test prints, which are almost invisible on a white background on white background thanks to the transparent filament: <gallery> anykeyx6_druckmuster_deckel.jpg | Print pattern for the keys </gallery> As strain relief for the permanently installed USB cable, there is a small ramp behind the U-shaped cut-out and a hole through for a cable tie. The ramp only serves to prevent the cable tie from pressing down the lower half of the housing. One could speculate that the stair structure caused by the print layers might even help the cable to not slip out. 3 holes, through which M2.5 screws fit, are used to hold everything together. There were 4 iterations in total, but only two of them found their way to the printer - and that only because the first part lifted off the printing bed and thus was warped. Apparently the STL data is not quite clean, so the model is probably a bit hanging in the air. With a microstep of -0.001 in the Z-direction, the printing result was better, but the first layer is still a bit grubby... <gallery> anykeyx6_sketchup_deckel.png | 3D model of the upper shell anykeyx6_deckel_vergurkt.jpg | The first try (warped) anykeyx6_Deckel.jpg | The better print. </gallery> The lower part of the case is actually 7 parts and needed no revision (but a small operation with the scalpel). The complexity is also much lower. The 4 "chimneys" are striking at first - the idea behind them is to insert nuts and screw them to the upper part of the case. The whole thing is (rather unintentionally) designed for compression, both for the nut and towards the other part of the housing. At least nothing slips. There are blind holes/indents at the positions of the buttons - for a very simple reason: save material and print time. The base plate should be thick enough to be stable but not to have to be printed a second time. In order to fit the buttons in height, small spacer nipples are used, which are small and therefore can be adjusted and printed very quickly. Because I didn't have any super glue left, they are only fixed on one side on the base plate with double sided adhesive tape. <gallery> anykeyx6_sketchup_bodenplatte.png | 3D model of the bottom plate anykeyx6_shim.png | The 3D model of a nipple anykeyx6_bodenplatte_benippelt.jpg | Floor plate with nuts and nipples (and I thought this was bad in German) </gallery> All in all, the printer was busy for about 4 hours, although it was not running at maximum speed. The material costs are (without samples and misprints) about 50 cent if I am not mistaken, so not really worth mentioning. =Assembly= Originally I planned to use an Atmega8 in a DIP package. But since it would have been a bit tight, I decided to use one in a TQFP package. Besides the microcontroller, the 9 transistors for LED control are also located on the self-made dot matrix board: <gallery> anykeyx6_platine.jpg | Assembled circuit board </gallery> The LED keys are fitted with long connecting leads made of enamelled copper wire, which are beeped through and stuck on correspondingly labelled tape strips. Twisted and soldered together, they then are connected the FETs. Same procedure for the ground of the switches. <gallery> anykeyx6_tastenverdrahtung.jpg | Tidying up the chaos </gallery> To prevent the keys from repeatedly slipping out of their holes when the housing is closed, tape is applied to the outside of the case. For safety reasons, it is labeled with numbers so that nothing can go wrong with turning and mirroring. Keys inserted, cables laid in the case and the copper ball is formed. Cable spaghetti, anyone? The USB cable is firmly lashed down and has a very tight bending radius in the case - it's in (hopefully). <gallery> anykeyx6_boden_und_deckel.jpg | both halves of the housing anykeyx6_deckel_verklebt.jpg | some assembly aid anykeyx6_deckel_assy.jpg | lid with inserted components </gallery> The nipples are already glued into the lower half of the housing and it gets exciting: does it fit? Unfortunately there are no countersunk screws in the part box, so it remains a bit ugly with the galvanized cylinder head screws. Or pragmatic. Well, it holds - and the buttons are in the case in such a way that they neither (too much) rattle nor are they pressed permanently. Success! :) To give the buttons some more meaning, the upper row is decorated with a label of some symbols from FontAwesome. Now nothing should go wrong. =Software= ==first test== The first test software is written in Python and lets a rainbow run through. For the sake of simplicity, it only changes one LED at a time: <source lang="python"> import hid import time import colorsys devices = hid.enumerate(0x16C0, 0x05DF) if len(devices) == 0: print("no devices found") exit() dev = hid.device() dev.open_path(devices[0]['path']) def setled(dev, index, color): r = int(color[0] * 255) g = int(color[1] * 255) b = int(color[2] * 255) dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) d = 60 while True: for h in range(0, 360): for i in range(0, 6): setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1)) time.sleep(0.02) </source> As a snapshot, it looks something like this: <gallery> anykeyx6_rgb_demo.jpg | colors, yay! </gallery> ==The OBS Client== Due to the lack of deep knowledge in C++, I don't even try to write a real plugin for OBS. Instead I use [https://github.com/Palakis/obs-websocket obs-websocket], which provides an API for C# that is extremely easy to use. For the buttons, an extremely rudimentary class is hacked together. No error handling at all. The buttons are read out in a background worker that fires events (and also determines the duration of the press when released), the LED colors are set for all 6 buttons in one method. Here you can also see how hastily cobbled together it is: Between writing the two "sets" of color, the software sleeps for a millisecond. The reason is both simply and stupid: if you write too fast, the first of the two data packets may be lost in the firmware, because the transfer is not (if you want to call it that) threadsafe. The GUI only has a "Connect" button that should only be pressed when OBS is running and the hardware is connected. The configuration is also rather basic and can be found in AnykeyOBS.exe.config Here you can store the active/inactive colors for each button as hex code (or named color, untested), define the function and give an argument for this function. To assign a scene, pack into the function "Scene" and write the corresponding scene name into the argument. For recording, the function is called "Record" and the argument can be defined as "Toggle", "Start" and "Stop". Streaming is not yet supported. For reasons not quite understandable to me, the state of streaming/recording can only be determined by events. Therefore, the key with the corresponding assignment remains orange when the program is started. This is also the (hard coded) color for transitions between recording and no recording. Another feature is the cancelling of actions - basically they are only triggered when the button is released - unless the button is held for more than one second. In this case the action is cancelled. All in all, the software can at best be described as a proof of concept. It works, somehow. ===First fire=== In the meantime I was even allowed to visit my sister to give her the hardware. yay! But the setup was done online, though. Got obs-websocks installed, copied AnykeyOBS on the tablet and: Exception. <pre> ************** Ausnahmetext ************** System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden bei SimplerHid.HidDevice.GetName(IntPtr handle) bei SimplerHid.HidDevice.GetInfoSets() bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber) bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e) bei System.Windows.Forms.Control.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnClick(EventArgs e) bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bei System.Windows.Forms.Control.WndProc(Message& m) bei System.Windows.Forms.ButtonBase.WndProc(Message& m) bei System.Windows.Forms.Button.WndProc(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) </pre> Shit. The presumed cause is quickly located: Some USB devices' name can't be read. Thrown a pack of try-catch on the problem and a pinch of <code>Console.WriteLine</code>s and the program stays open after clicking "Connect". "Do the buttons light up?" - "Oh man, how cool" - "So yes?" After that I only heard wild clicking. I think she likes it. And this is what it looks like: [[Datei:anykeyx6_demo.mp4|500px]] =Conclusion= Where to start? For the good, the bad or the things I'm ashamed of? Bottom line: for a very shirt-sleeved piece of hardware, it looks (without me wanting to praise myself) quite decent. It only gets bad when you look under the hood. But at least that's pretty consistent. The good: * My sister has something that I hope will make her job a little easier * I've learned a about 3D printing again * It's been a lot of fun * It's quite colorful The bad: * Decoupling, what decoupling? * LEDs ** Not very bright ** Flickering during USB traffic (due to INT0) ** Too bright in dark surroundings and poorly visible in bright daylight * Changes of dropped packets for LED settings and key presses are quite high * Buttons ** Can also be operated from the bottom of the housing ** Relatively loud (can be heard in the video) ** Wobble, are crooked and have no guidance * Software ** Rudimentary in all manners, if anything fails, everything's gone ** No automatic connection to OBS and the hardware ** No GUI for configuration ** Virtually no functions supported in OBS ** No other functions except OBS control * No standby states =Downloads= * [[Datei:Anykeyx6.zip]] SketchUp files, associated STLs, firmware and C# software to talk to OBS. [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] [[Kategorie:English translation]] 238a0eebe1768b64388eba1536fa2b62e1793596 Hobbyelektronik.org:Impressum 4 4 1593 1548 2020-05-11T18:55:38Z Chris 2 /* Spenden */ Spaß mit Homoglyphen wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung nur eine Konversation in 2-3 Jahren mit verschlüsselten Mails stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Es geht um Dinge, die mich interessieren (oder einmal interessierten). Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schnell (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzprüfung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich "übrige" Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das "schlechte Gewissen" zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine "Win-Win-Win-Situation": Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, genauso die Kosten für den Versand.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. "Absolut richtig" zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und "Bettelbriefe" steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) b99e2f122f7784f17aa5589f44c238f16df841d6 1594 1593 2020-05-11T19:11:28Z Chris 2 /* Spenden */ Spaß mit Homoglyphen wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung nur eine Konversation in 2-3 Jahren mit verschlüsselten Mails stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Es geht um Dinge, die mich interessieren (oder einmal interessierten). Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schnell (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzprüfung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich „übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das ''schlechte Gewissen'' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine "Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, genauso die Kosten für den Versand.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) cd8e3e58317663a97624230a6d724e09077d4dfd 1596 1594 2020-05-31T12:17:43Z Chris 2 /* Spenden */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung nur eine Konversation in 2-3 Jahren mit verschlüsselten Mails stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Es geht um Dinge, die mich interessieren (oder einmal interessierten). Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schnell (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzprüfung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine "Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) ae560e810b9cf8934dd8cc8aa6e0fa45bbc42ff2 1597 1596 2020-06-03T08:49:54Z Chris 2 /* Spenden */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung nur eine Konversation in 2-3 Jahren mit verschlüsselten Mails stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Es geht um Dinge, die mich interessieren (oder einmal interessierten). Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schnell (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzprüfung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) a051dab512ecece5ab17e9ee58bacd3cfb5e101f 1598 1597 2020-12-07T20:02:40Z Chris 2 /* Kontakt */ Mails in English are also welcome wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org For those who don't speak German: feel free to write me in English. E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung nur eine Konversation in 2-3 Jahren mit verschlüsselten Mails stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Es geht um Dinge, die mich interessieren (oder einmal interessierten). Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schnell (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzprüfung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nicht durch externe Einflussnahme geschrieben. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) 9d7f5edf8f511f11cf4a1129e89a007bbddff145 VBus-Decoder 0 120 1595 1451 2020-05-20T17:16:48Z Chris 2 /* VBus-Adapter für den Raspberry Pi */ Hinweis zur Fehlfunktion der LED wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} In unserer Solaranlage arbeitet ein Viessmann Vitosolic 200, der die Regelung der Anlage übernimmt. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem keinerlei Informationen verfügbar sind. Beim VBus sieht es schon ein wenig anders aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen diverser Meinungen - überhaupt keine Ähnlichkeiten zu RS485 hat. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2V und 35mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170 =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <pre> 0xAA, 0x10, 0x00, 0x21, 0x73, 0x10, 0x00, 0x01, 0x12, 0x38, 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x38, 0x22, 0x38, 0x22, 0x05, 0x46 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37 0x47, 0x00, 0x00, 0x00, 0x00, 0x38 0x64, 0x64, 0x00, 0x00, 0x00, 0x37 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D 0x01, 0x03, 0x60, 0x02, 0x04, 0x15 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D </pre> Zu allererst wird ein 10 Byte langer Kopf gesendet, der mit einem eindeutigen Sync-Wort (0xAA) beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird das MSB belegt. Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen Ziel- und Quelladresse (0x0010 <= 0x7321), die Protokollversion (0x10), der ausgeführte Befehl (0x0100) und die Anzahl der danach folgenden Nutzpakete (0x12). Abschließend wird eine Prüfsumme (0x38) der zuvor gesendeten Daten übertragen. Im Anschluss des Headers werden n Datenframes mit je 6 Byte Länge geschickt. Die ersten 4 enthalten Nutzdaten, im 5. wird ein Septett geschickt und abschließend erfolgt wieder eine Checksum. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen kann, dürfen folgende Daten kein höchstwertiges Bit enthalten. Dieses findet sich jeweils im Septett. Das ist auch schon das gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Hintergrund== Noch eine kleine Hintergrundinformation, worum es sich bei der Ziel- und Quell-Adresse handelt. Die Quelladresse ist selbstverständlich der Regler (0x7321 = Vitosolic 200 [Regler]), die Zieladresse (0x0010) wird in der kompletten Dokumentation nur als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät, der '''D'''aten'''f'''ern'''a'''nzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Software= Die Software ist, wie immer, in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> ==Debug-Ausgabe== [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei %ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. ==Bekannte Fehler/Macken== [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: *Einstrahlung *Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) *Unbekannt-Felder ** anscheinend immer 0x00 *Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: *RAM-Belegung *Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) *Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Hardware für den PC= Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> Die Daten für EAGLE befinden sich im Download-Bereich. =VBus-Adapter Nano= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. ==Aufbau== Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch ==Messung== Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. ==Troubleshooting== Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. ==Leiterkarten== Es gibt wieder Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =VBus-Adapter für den Raspberry Pi= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. ==Fehler & Verbesserungen== Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. ==Leiterkarten== Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. ==Weiteres== Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. ==Kostenreduzierte Variante/v1.2== Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ===Die Enttäuschung=== Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ===Die Lösung=== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Python-Implementierung= Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie und Gewährleistung: * [[Datei:VBus-Python.zip]] =Download= *[[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 *[[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz *[[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 *[[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano *[[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi *[[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solar-Anlage]] fd5c160c51bad58fffe7a6c0110f8e850c018dd7 1604 1595 2021-02-09T20:12:09Z Chris 2 Seite entschlackt und in Unterseiten aufgeteilt. wikitext text/x-wiki *Main* [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. Allerdings scheint Resol bei ein paar Reglern eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden - was mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= '''Achtung: Die Schaltung enthalten aktuell teilweise Fehler, die aktuell überarbeitet werden. Bitte also mit Vorsicht genießen, bis dieser Hinweis entfernt wurde.''' Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: ==[[VBus-Decoder/RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8|AVR8-Plattform findet sich auf der entsprechenden Unterseite]]. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 073ad03014f5d5c22e129cf6acdfd35ef8ab81e6 1605 1604 2021-02-09T20:12:22Z Chris 2 wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. Allerdings scheint Resol bei ein paar Reglern eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden - was mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= '''Achtung: Die Schaltung enthalten aktuell teilweise Fehler, die aktuell überarbeitet werden. Bitte also mit Vorsicht genießen, bis dieser Hinweis entfernt wurde.''' Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: ==[[VBus-Decoder/RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8|AVR8-Plattform findet sich auf der entsprechenden Unterseite]]. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 5e1885642d09aa6301dbef2ade5fed82741ae22f 1606 1605 2021-02-09T20:13:06Z Chris 2 /* Adapter für RS-232 */ Link korrigiert wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. Allerdings scheint Resol bei ein paar Reglern eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden - was mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= '''Achtung: Die Schaltung enthalten aktuell teilweise Fehler, die aktuell überarbeitet werden. Bitte also mit Vorsicht genießen, bis dieser Hinweis entfernt wurde.''' Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8|AVR8-Plattform findet sich auf der entsprechenden Unterseite]]. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 23ed3b50285dc603279a713fffbef5ab21af7a81 1607 1606 2021-02-09T20:15:16Z Chris 2 /* Hardware */ Hinweis auf Links in Überschriften wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardwareschnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. Allerdings scheint Resol bei ein paar Reglern eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden - was mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen. Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= '''Achtung: Die Schaltung enthalten aktuell teilweise Fehler, die aktuell überarbeitet werden. Bitte also mit Vorsicht genießen, bis dieser Hinweis entfernt wurde.''' Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8|AVR8-Plattform findet sich auf der entsprechenden Unterseite]]. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 2bfcd5a7adcb02cf3ffa79d499c62eeec56d5a53 1617 1607 2021-02-09T20:37:16Z Chris 2 /* Hardwareschnittstelle */ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Allerdings scheint Resol bei ein paar Reglern eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden - was mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= '''Achtung: Die Schaltung enthalten aktuell teilweise Fehler, die aktuell überarbeitet werden. Bitte also mit Vorsicht genießen, bis dieser Hinweis entfernt wurde.''' Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8|AVR8-Plattform findet sich auf der entsprechenden Unterseite]]. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] ee1c577e27a6196103198a5bcadc9a28fe073cb4 1618 1617 2021-02-09T20:37:53Z Chris 2 /* AVR8 */ Link korrigiert wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Allerdings scheint Resol bei ein paar Reglern eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden - was mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= '''Achtung: Die Schaltung enthalten aktuell teilweise Fehler, die aktuell überarbeitet werden. Bitte also mit Vorsicht genießen, bis dieser Hinweis entfernt wurde.''' Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 04e96a71803f81f720f37ecb7d984189d39a28ec 1633 1618 2021-02-26T20:37:46Z Chris 2 /* Adapter für den Raspberry Pi */ Empfehlung bzgl. Nachbau wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Allerdings scheint Resol bei ein paar Reglern eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden - was mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= '''Achtung: Die Schaltung enthalten aktuell teilweise Fehler, die aktuell überarbeitet werden. Bitte also mit Vorsicht genießen, bis dieser Hinweis entfernt wurde.''' Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Auchtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 03a16904d8f53fcb15e7e2180a19b9e656053c89 1634 1633 2021-02-26T20:38:27Z Chris 2 /* Adapter für den Raspberry Pi */ Link vervollständigt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Allerdings scheint Resol bei ein paar Reglern eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden - was mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= '''Achtung: Die Schaltung enthalten aktuell teilweise Fehler, die aktuell überarbeitet werden. Bitte also mit Vorsicht genießen, bis dieser Hinweis entfernt wurde.''' Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Auchtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 1a3f9e04500f190a1598016b82f480662173d48d 1636 1634 2021-02-26T20:50:45Z Chris 2 /* Hardware */ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Allerdings scheint Resol bei ein paar Reglern eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden - was mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Auchtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 363379f1e91524e154ece672644a75f9ed646bcf 1638 1636 2021-02-26T20:56:59Z Chris 2 /* Software */ Protokollanalysator hingzugefügt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Allerdings scheint Resol bei ein paar Reglern eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden - was mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Auchtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] ecba5c2865efbbb40e47a02a04ce94cc9bf60276 MediaWiki:Common.css 8 141 1599 1096 2021-02-01T21:38:01Z Qsysopr 1 Rand braucht das Land ;) css text/css /* <source lang="css"> */ /*-----------------------------------------------------------------------------------------------*/ /* ACHTUNG! Common.css enthält die gemeinsamen Skin-Anpassungen der deutschsprachigen Wikipedia */ /*---------------------------------------------------------------------------------------------*/ /* Common.css ist in drei grundlegende Abschnitte gegliedert: */ /* 1. Editierbare Seiteninhalte */ /* 2. Sonstige Anpassungen (Spezialseiten, u.a.) */ /* 3. Hauptseitenspezifisches */ /* Jede Ergänzung/Änderung muss vorher jeweils für alle Skins auf Tauglichkeit getestet werden, */ /* individuell per User.css! Ist hier erstmal geändert, dauert es dank Cache eine Weile, bis die */ /* Änderungen bei allen Nutzern sichtbar oder, bei Fehlern, korrigiert sind. */ /* +++++ 1. ANPASSUNGEN DER ANZEIGE VON EDITIERBAREN SEITENINHALTEN +++++ */ /* Personennamen in Kapitälchen: class="Person" */ .Person { display: inline; font-variant: small-caps; font-style: normal; } /* [[Wikipedia:Zitate|Zitate]] (siehe [[Vorlage:Zitat]]) */ p.Zitat { font-style: normal; margin-bottom: 0; } p.cite { margin-top: 0; padding-left: 1em; } /* [[Wikipedia:Quellenangaben|Quellenangaben]] nicht kursiv, da sie ggf. verschiedene Bestandteile enthalten */ cite { font-style: normal; } /* Stylesheet-Ergänzung zu Standard-[[Wikipedia:Navigationsleisten|Navigationsleisten]] */ div.BoxenVerschmelzen, div.NavFrame { margin: 1.5em 0 0; padding: 2px; border: 1px solid #aaaaaa; text-align: center; border-collapse: collapse; font-size: 95%; clear: both; } div.BoxenVerschmelzen div.NavFrame, div.NavFrame + div.NavFrame { margin-top: 0; } div.BoxenVerschmelzen div.NavFrame { border-style: none; border-style: hidden; } div.NavFrame + div.NavFrame { border-top-style: none; border-top-style: hidden; } div.NavPic { margin: 0; padding: 2px; float: left; } div.NavFrame div.NavHead { font-weight: bold; font-size: 100%; background-color: #efefef; } div.NavFrame p, div.NavFrame div.NavContent, div.NavFrame div.NavContent p { font-size: 100%; } div.NavEnd { margin: 0; padding: 0; line-height: 1px; clear: both; } /* Stylesheet fuer den 'Ausklappen'-Button an Navileisten, der in [[MediaWiki:Common.js]] implementiert wird */ .NavToggle { font-size: x-small; float: right; } /* Workaround für Internet Explorer 6 */ div.NavFrame, div.NavPic, .NavToggle { position: relative; } /* Stylesheet-Ergänzung zu SideBoxen (ehedem [[Wikipedia:TownBox|TownBox]]) */ div.sideBox { position: relative; float: right; background: white; margin-left: 1em; border: 1px solid gray; padding: 0.3em; width: 200px; overflow: hidden; clear: right; } div.sideBox dl { padding: 0; margin: 0 0 0.3em 0; font-size: 96%; } div.sideBox dl dt { background: none; margin: 0.4em 0 0 0; } div.sideBox dl dd { margin: 0.1em 0 0 1.1em; background-color: #f3f3f3; } /* Stylesheet-Ergänzung zu [[Wikipedia:Taxoboxen|Taxoboxen]] und [[Wikipedia:Paläoboxen|Paläoboxen]] */ table.taxobox, table.palaeobox { border-collapse: collapse; border: 1px solid gray; float: right; clear: right; margin-left: 0.5em; background-color: white; } table.taxobox th { background-color: #9bcd9b; } table.palaeobox th { background-color: #e7dcc3; } table.taxobox th, table.palaeobox th { border: solid 1px gray; text-align: center; font-weight: bold; } table.taxobox td, table.palaeobox td { vertical-align: top; } table.taxobox .Person, table.palaeobox .Person { font-style: normal; } table.taxobox div.thumb, table.taxobox div.thumb * { background-color: #f9f9f9; } table.taxobox div.thumb, table.taxobox div.thumb *, table.palaeobox div.thumb, table.palaeobox div.thumb * { margin: 0 auto; padding: 0; float: none; border: none; } table.taxobox div.magnify, table.palaeobox div.magnify { display: none; } table.taxobox tr td div.thumb div div.thumbcaption { text-align: center; } table.palaeobox tr td div.thumb div div.thumbcaption { text-align: left; } table.taxobox td.Person, table.palaeobox td.Person { text-align: center; display: block; } table.taxobox td.taxo-name, table.taxobox td.taxo-bild, table.palaeobox td.taxo-name, table.palaeobox td.taxo-bild, table.palaeobox td.taxo-zeit { text-align: center; } table.palaeobox td.taxo-ort { text-align: left; } /* aus Vorlage zur Entlastung, skinabhängigen Darstellung und Kombinierbarkeit hierher ausgelagert */ .wikitable, .prettytable { margin: 1em 1em 1em 0; background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse; } .prettytable th, .prettytable td { border: 1px #aaa solid; padding: 0.2em; } .prettytable th { text-align: center; } .prettytable caption { font-weight: bold; } /* Zebra-Tabellen */ table.wikitable.zebra tr:nth-child(even) { background: white; } .nogrid th, .nogrid td { border: none; } div.float-left, table.float-left, .float-left { float: left; clear: left; } div.float-right, table.float-right, .float-right { float: right; clear: right; margin: 1em 0 1em 1em; } div.centered, table.centered, .centered { margin-left: auto; margin-right: auto; } .toptextcells td { vertical-align: top; } /* Bitte KEINE weiteren Definitionen dieser Art für Boxen hier, das gehört in entsprechende Vorlagen! */ /* Hier 20 Mal Trivialitäten wie "text-align:center" zu definieren verlangsamt alles und ist nicht */ /* Sinn der Sache. (Und wer nicht weiß warum, hat's nicht verstanden.) */ /* Do not expand [[Wikipedia:WikiProjekt Georeferenzierung|kvaleberg.com-URLs]] for printing */ #content span.coordinates a.external.text:after, #content span.coordinates a.external.autonumber:after, #content div.coordinates a.external.text:after, #content div.coordinates a.external.autonumber:after { content: ""; } /* Do not expand URLs for printing */ #content span.plainlinks-print a.external.text:after, #content span.plainlinks-print a.external.autonumber:after, #content div.plainlinks-print a.external.text:after, #content div.plainlinks-print a.external.autonumber:after { content: ""; } /* Metadaten (bspw. [[Wikipedia:Personendaten|Personendaten]]) */ table.metadata { border: 1px solid #aaaaaa; display: none; } .metadata-label { color: #aaaaaa; } span.metadata, span.metadata-inline { display: none; } /* * Farbdefinitionen für Rahmen und Hintergründe von [[Wikipedia:Textbausteine|Textbausteinen]]. * Hier: Standardvorgaben für "dunkle Schrift auf hellem Grund". * Für Hell-auf-dunkel-Skins ([[MediaWiki:Amethyst.css|Amethyst]]) müssen dort entsprechende Definitionen * zusätzlich eingetragen werden! Anpassungen für andere Skins sind optional. * (Die Angaben der Rahmenstärke dienen der Bequemlichkeit, so dass man * für dünne Rahmen nur noch "border-style" angeben muss.) */ .rahmenfarbe1 { /* Wie Inhaltsverzeichnis */ border-color: #aaaaaa; border-width: 1px; } .rahmenfarbe2 { /* Unauffällig, geringer Kontrast */ border-color: #e9e9e9; border-width: 1px; } .rahmenfarbe3 { /* "Rot", auffällig */ border-color: #c00000; border-width: 1px; } .rahmenfarbe4 { /* Neutrale Farbe, deutlich */ border-color: #8888aa; border-width: 1px; } .rahmenfarbe5 { /* "Schwarz", hoher Kontrast */ border-color: #000000; border-width: 1px; } tr.hintergrundfarbe1 th, tr th.hintergrundfarbe1, table.hintergrundfarbe1, .hintergrundfarbe1 { /* Wie Inhaltsverzeichnis */ background-color: #f9f9f9; } tr.hintergrundfarbe2 th, tr th.hintergrundfarbe2, table.hintergrundfarbe2, .hintergrundfarbe2 { /* "Weiß", für Nicht-Artikel-Seiten, neutral */ background-color: #ffffff; } tr.hintergrundfarbe3 th, tr th.hintergrundfarbe3, table.hintergrundfarbe3, .hintergrundfarbe3 { /* "Gelb", auffällig */ background-color: #ffff40; } tr.hintergrundfarbe4 th, tr th.hintergrundfarbe4, table.hintergrundfarbe4, .hintergrundfarbe4 { /* Sehr auffällig */ background-color: #ffaa00; } tr.hintergrundfarbe5 th, tr th.hintergrundfarbe5, table.hintergrundfarbe5, .hintergrundfarbe5 { /* Neutral, abgesetzt */ background-color: #e0e0e0; } tr.hintergrundfarbe6 th, tr th.hintergrundfarbe6, table.hintergrundfarbe6, .hintergrundfarbe6 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b3b7ff; } tr.hintergrundfarbe7 th, tr th.hintergrundfarbe7, table.hintergrundfarbe7, .hintergrundfarbe7 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffcbcb; } tr.hintergrundfarbe8 th, tr th.hintergrundfarbe8, table.hintergrundfarbe8, .hintergrundfarbe8 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffebad; } tr.hintergrundfarbe9 th, tr th.hintergrundfarbe9, table.hintergrundfarbe9, .hintergrundfarbe9 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b9ffc5; } /* Keine Vergrößerung der Zeilenhöhe durch hochgestellte Zahlen der Fußnoten */ sup.reference { font-weight: 400; font-style: normal; } sup, sub { line-height: 1em; } /* Hervorhebung der angeklickten Fußnoten und der Rückverweise in blau */ ol.references > li:target, sup.reference:target { background-color: #def; } /* Hochgestellte Buchstaben in der Einzelnachweiseliste kursiv setzen */ ol.references li a[href|="#cite_ref"] { font-style: italic; } /* Inline-Verwendung der [[:Kategorie:Vorlage:Schwesterprojektverweis|Schwesterprojektverweise]] */ ol.references li div.sisterproject { display: inline !important; } /* Für <nowiki><hiero>…</hiero></nowiki> */ .mw-hierotable, .mw-hierotable th, .mw-hierotable td { border: 0; padding: 0; } /* Für [[MediaWiki:Anoneditwarning]] und weitere Hinweise, die alle untereinander stehen */ #mw-anon-edit-warning, #mw-missingsummary, #wp_talkpagetext { width: 80%; background: #d3e1f2; border: 1px solid #1a47ff; margin: 1em auto; padding: 1em; } /* Bei URLs, die auf unser Projekt und verwandte Projekte verweisen, den Pfeil ausblenden * Dieser Pfeil dient nur dazu, auf externe Ziele hinzuweisen * Auf den Einsatz der Klasse "plainlinks" kann dadurch verzichtet werden */ #content a[href^="http://de.wikipedia.org"], #content a[href^="http://toolserver.org"] { background: none !important; padding-right: 0 !important; } #content .mw-search-formheader div.search-types ul li a[href^="http://de.wikipedia.org"], #content .mw-search-formheader div.search-types ul li a[href^="http://toolserver.org"] { padding-right: 0.5em !important; } /* Falls bei der Seitenbearbeitung vergessen wurde, die Zusammenfassung auszufüllen */ .mw-summarymissed { border: 5px solid red; padding: 2px; } /* Copyrightwarnung */ #editpage-copywarn { border: solid 1px #c00000; font-size: 90%; background-color: #ffffff; } .mw-tos-summary { border: solid 1px #c00000; background-color: #ffffff; padding-left: 1em; } /* +++++ 2. SONSTIGE ANPASSUNGEN (Spezialseiten u. a.) +++++ */ /* Markierung von Redirects in [[Special:Allpages]], [[Special:Watchlist]], Kategorien */ .allpagesredirect, .watchlistredir, .redirect-in-category { font-style: italic; } /* Fettformatierung von Admin-Spezialseiten in [[Special:Specialpages]] abschalten */ .mw-specialpagerestricted strong { font-weight: normal; } /* Legende auf [[Special:Specialpages]] ebenfalls abschalten */ div.mw-specialpages-notes { display: none; } /* Größerer Abstand zwischen TOC-Nummerierung und TOC-Eintrag */ span.tocnumber { margin-right: 0.3em; } /* Skinabhängige absolute Positionierungen ausblenden */ /* Bitte [[MediaWiki Diskussion:Common.css#Absolute_Positionierungen]] beachten */ #coordinates, #coordinates_3_ObenRechts, #issnlink, #editcount, #shortcut, #artikelstadium, .topicon, #spoken-icon, #commons-icon { display: none; } /* Anpassungen für [[:Template:Link_FA]] */ /* hide the template */ #bodyContent span.FA { display: none; } /* change the bullets for links to special articles */ #p-lang li.FA { /* hier immer auch linkFA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/d/d0/Monobook-bullet-star-transparent.png"); } /* change the bullets for links to special articles */ #p-lang li.GA { /* hier immer auch linkGA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/a/a1/Monobook-bullet-star-gray.png"); } /* Verhindere, dass Infoboxen etc. in den Inhalt von Kategorien hineinragen. Das betrifft nur Kategorieseiten. */ #mw-subcategories, #mw-pages { clear: both; } /* DIVs in ImageMaps inlinen (Vorschlag von Revolus) */ .imagemap-inline div { display: inline; } /* [[Special:Hochladen]]: Warnmeldung auf bestehende Dateien, unerwünschte Prefixe usw. deutlicher hervorheben. */ #wpDestFile-warning ul { border: solid red 1px; padding: 1.5em; } /* Warnmeldung für gesperrte Titel */ .mw-titleprotectedwarning { background-color: #eee; border: 2px solid red; padding: 1em; } /* Warnmeldung bei der Bearbeitung von Seiten im MediaWiki-Namensraum */ .mw-editinginterface { background-color: #f9f9f9; border-color: #c00000; border-width: 1px; border-style: solid; padding: 2px; } /* Überschrift 5. und 6. Ordnung proportionaler zu Fließtext */ #content h5 { font-size: 108%; /* Original: 116% */ } #content h6 { font-size: 100%; /* Original: 80% = kleiner als Bodytext, unschön */ } #content h6 .editsection { font-size: 120%; font-weight: normal; } /* Anleitung auf Special:Search */ .mw-searchresult { font-size: 84%; margin: 5px; } /* Gestaltung der Edittools-Leiste */ #specialchars { margin-top: 3px; border: solid 1px #aaaaaa; padding: 1px; text-align: left; background-color: white; } /* Legende für Versionsgeschichte */ .mw-history-legend { font-size: 90%; margin-top: 2px; margin-bottom: 2px; border: solid 1px #e9e9e9; padding: 0 5px 5px 5px; background-color: #f9f9f9; clear: both; } /* +++++ 3. NEUE [[Wikipedia:Hauptseite|HAUPTSEITE]] (ab 2006) +++++ */ /* Kategorie verbergen */ /* Überschrift verbergen */ /* Redirhinweis verbergen - ACHTUNG: Je nach Skin muss jetzt der Abstand zum oberen Rand korrigiert werden */ body.page-Wikipedia_Hauptseite #catlinks, body.page-Wikipedia_Hauptseite h1.firstHeading, body.page-Wikipedia_Hauptseite #contentSub { display: none; } #hauptseite h2 { background-color: #d8e8ff; border: 1px solid #8898bf; font-size: 1em; font-weight: bold; margin-top: 0; margin-bottom: 0; padding-top: 0.1em; padding-bottom: 0.1em; } #hauptseite .inhalt { background-color: #ffffff; border: 1px solid #8898bf; border-top: 0 solid white; padding: 0.3em 0.8em 0.4em 0.8em; } #hauptseite .inhalt hr { background-color: #8898bf; color: #8898bf; height: 1px; margin: 0.5em 0; padding: 0; } #hauptseite .inhalt .mehr { clear: both; font-size: 95%; margin-top: 0.8em; text-align: right; } #hauptseite table { background-color: transparent; } .hauptseite-oben, .hauptseite-links, .hauptseite-rechts { margin-bottom: 1em; } .hauptseite-links { margin-right: 0.5em; } .hauptseite-rechts { margin-left: 0.5em; } .hauptseite-oben h2, .hauptseite-unten h2 { text-align: center; } .hauptseite-oben .inhalt .portale { font-weight: bold; margin-top: 0.2em; margin-bottom: 0.2em; } .hauptseite-oben .inhalt .intern { font-size: 90%; text-align: center; } .hauptseite-links h2, .hauptseite-rechts h2 { text-indent: 0.8em; } #hauptseite-schwesterprojekte .inhalt a { font-weight: bold; } /* IPA links nicht unterstreichen */ .IPA a:link, .IPA a:visited { text-decoration: none; } /* CSS-Klassen für Schriftarten als Workaround für Defizite in alten IE-Versionen. * Achtung: IE6 mag keine Zeilenumbrüche zwischen den Fonts. * In IE8 nicht mehr nötig, soll mit den alten Versionen aussterben. Browserweiche: * http://www.dynamicsitesolutions.com/css/filters/star-html/ * http://www.dynamicsitesolutions.com/css/filters/first-child-plus-html/ */ * html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } *:first-child+html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } * html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } *:first-child+html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } * html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } *:first-child+html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } * html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } *:first-child+html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } * html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } *:first-child+html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } * html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } *:first-child+html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } * html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } *:first-child+html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } * html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } *:first-child+html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } * html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } *:first-child+html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } /* Standardmäßige Ausblendung der Flagged-Revisions-Backlog-Sitenotice */ #mw-oldreviewed-notice { display: none; } /* Standardmäßige Ausblendung der Flagged-Revisions-Kommentarbox */ #mw-commentbox { display: none; } /* Abstand zwischen Liste und Inhaltsverzeichnis erhöhen, siehe http://de.wikipedia.org/w/index.php?title=MediaWiki_Diskussion:Common.css&oldid=51639015#Abstand_vor_Inhaltsverzeichnis */ ul + .toc, ol + .toc { margin-top: 0.5em; } /* höheres Uploadfeld */ #wpUploadDescription { height: 20em; } /* Im Projekt WP:GEO benutzt die [[Vorlage:Coordinate]] das «geo-microformat» zur semantischen Auszeichnung des Texts. Der Inhalt dieses [[Tag (Informatik)|Tags]] ist nicht für den Leser bestimmt. */ .geo { display: none; } /* Patrollink ausblenden, da die Eweiterung hier nicht aktiviert ist und deren Optik zu sehr den gesichteten Versionen ähnelt. */ .fr-diff-patrollink, .patrollink { display: none; } /* Rollback-Knopf auf Beobachtungsliste ausblenden, da es dort nur von sehr beschränktem Nutzen ist und zu sehr vielen Reverts aus Versehen führt */ .page-Spezial_Beobachtungsliste .mw-rollback-link { display: none; } /* </source> */ /* Disable Discussion-tab */ #ca-talk { display: none; } /* reset code style */ code { background-color: none !important; border: none !important; border-radius: 0; padding: 0; } pre { white-space: pre; } /* highlighting */ .hb1 { background-color: #C1F5C1; } .hb2 { background-color: #CDC2EF; } .hb3 { background-color: #FFF6C9; } .hb4 { background-color: #FFC9C9; } .hb5 { background-color: #BED8ED; } .hb6 { background-color: #EDBBED; } .hb7 { background-color: #F4FDC7; } .hb8 { background-color: #FFE8C9; } .hf1 { color: #66D766; } .hf2 { color: #7C67C0; } .hf3 { color: #FFE879; } .hf4 { color: #FF7979; } .hf5 { color: #5D90B7; } .hf6 { color: #B857B8; } .hf7 { color: #E2F876; } .hf8 { color: #FFC679; } .he0 { border: 1px solid grey; border-radius: 4px; } .he1 { border: 1px solid #66D766; border-radius: 4px; } .he2 { border: 1px solid #7C67C0; border-radius: 4px; } .he3 { border: 1px solid #FFE879; border-radius: 4px; } .he4 { border: 1px solid #FF7979; border-radius: 4px; } .he5 { border: 1px solid #5D90B7; border-radius: 4px; } .he6 { border: 1px solid #B857B8; border-radius: 4px; } .he7 { border: 1px solid #E2F876; border-radius: 4px; } .he8 { border: 1px solid #FFC679; border-radius: 4px; } 338031676607b0e7db72b147305de9e8d09930c9 VBus-Decoder/Adapter für RS-232 0 704 1600 2021-02-09T18:54:34Z Chris 2 Seite erstellt wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann mit dieser Hardware den VBus anbinden. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> =Downloads= * [[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.5.0 [[Kategorie:PC]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 800b68b16ce96a1a40ad8fc701e5b641688fe55f VBus-Decoder/Adapter Nano 0 705 1601 2021-02-09T20:01:13Z Chris 2 Seite erstellt wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. =Aufbau= Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch =Messung= Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. =Troubleshooting= Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. =Leiterkarten= Es gibt wieder Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] c5966aed5dbd84e9180f90c76bbca31c189b9d32 1613 1601 2021-02-09T20:31:25Z Chris 2 Überschrift hinzugefügt, damit das Inhaltsverzeichnis oben platziert wird wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Einleitung= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum Platzsparenden fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. =Aufbau= Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch =Messung= Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. =Troubleshooting= Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. =Leiterkarten= Es gibt wieder Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] fd06c6ce60b87d79674cb2709b5cad16626253ac 1616 1613 2021-02-09T20:34:52Z Chris 2 /* Einleitung */ groß/Kleinschreibung korrigiert wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Einleitung= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum platzsparenden Fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. =Aufbau= Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch =Messung= Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. =Troubleshooting= Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. =Leiterkarten= Es gibt wieder Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] fe6e51b0b05002cbfa68e0db69f7a65454e6bfe8 VBus-Decoder/Adapter für den Raspberry Pi 0 706 1602 2021-02-09T20:02:35Z Chris 2 Seite erstellt wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. ==Fehler & Verbesserungen== Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. ==Leiterkarten== Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. ==Weiteres== Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. ==Kostenreduzierte Variante/v1.2== Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ===Die Enttäuschung=== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ====Die (vermeintliche) Lösung==== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 0554acff8682f34f01b01d4942e3ec09614c93c6 1614 1602 2021-02-09T20:31:47Z Chris 2 Überschrift hinzugefügt, damit das Inhaltsverzeichnis oben platziert wird wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. ==Fehler & Verbesserungen== Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. ==Leiterkarten== Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. ==Weiteres== Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. ==Kostenreduzierte Variante/v1.2== Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ===Die Enttäuschung=== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ====Die (vermeintliche) Lösung==== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 56db2d4725f800de2f5339c6c3eae2ba518d5902 1615 1614 2021-02-09T20:33:33Z Chris 2 Überschriftentiefe korrigiert wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Leiterkarten= Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =Kostenreduzierte Variante/v1.2= Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ==Die Enttäuschung== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ==Die (vermeintliche) Lösung== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 98356b3db32baeddd2d80776245824fb9517e11d 1620 1615 2021-02-21T21:27:01Z Chris 2 /* Die Enttäuschung */ Link korrigiert wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Leiterkarten= Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =Kostenreduzierte Variante/v1.2= Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ==Die Enttäuschung== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers]], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ==Die (vermeintliche) Lösung== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 51fd556bf5526c50525dcbb7f8fedd5dbac6a6fd 1630 1620 2021-02-26T20:30:04Z Chris 2 /* Die Enttäuschung - Teil 2 */ hinzugefügt wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Leiterkarten= Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =Kostenreduzierte Variante/v1.2= Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ==Die Enttäuschung== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers]], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ==Die (vermeintliche) Lösung== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} ==Die Enttäuschung - Teil 2== Stefan schickte eine Mail mit einen sehr guten Verbesserungsvorschlag bzw. vielmehr Hinweis auf Fehler: <pre> Ich würde an deiner Stelle bei der 3,3V Schaltung den Spannungsteiler R8/R5 anpassen. An dessen Eingang können ~7V anliegen womit der OP dann 3,5V an seinem Eingang hat. Das ist bei 3,3V Versorgungsspannung etwas über der Spezifikation des verwendeten OPs. </pre> Das ist absolut richtig, die Spannung ist außerhalb der Spec. Der Fehler hat sich mit an Sicherheit grenzender Wahrscheinlichkeit eingeschlichen, weil beim Neudimensionieren der Schaltung nur die Teile berücksichtigt wurden, die direkt an +3V3 hängen. Schaut man noch etwas genauer ins Datenblatt entdeckt man, dass die Eingänge des LM393 für eine korrekte Funktion einen gewissen Abstand zu V+ haben müssen. Bei der Variante von TI sind das VDD - 1,5 V. Ok, das ist natürlich Mist. Aber beherrschbarer. Im Prinzip müssen nur die Widerstände für die Spannungsteiler neu berechnet werden. Jetzt kann man es sich natürlich einfach machen und die naheliegendsten Werte aus der E24-Reihe nehmen. Selbst für gut ausgestattete Widerstandslager zu Hause würde das eine Bestellung bei den üblichen Verdächtigen bedeuten. Dann hat man meistens noch die vermutlich selten genutzten Wert-Überreste in einer Schublade liegen und das Bestücken ist fehleranfälliger. Uncool. Also warum nicht so lange mit den Bauteilwerten jonglieren, bis es eine gute Kombination gibt? Kann man manuell machen, ist aber eher mühsam. Geht auch mit Excel, ist aber auch nicht das beste Tool dafür. Ob JavaScript so wirklich dafür geeignet ist, sei mal dahingestellt - dafür spricht allerdings, dass mittlerweile fast jedes Endgerät mit Farbdisplay eine passende Laufzeitumgebung installiert hat. Herausgekommen ist dieser [//hobbyelektronik.org/tools/komparator/ schlichte Rechner]. Zahlen eingeben und los geht's: {| class="wikitable" ! Bezeichnung || Wert || Kommentar |- | Versorgungsspannung Komparator || 3,3 V || |- | Maximale Eingangsspannung Komparator || 1,8 V || (3,3 - 1,5) V |- | Maximale Signalspannung || 6,8 V || (8,2 - 1,4) V |- | Obere Schwelle || 4,5 V || aus der VBus-Spec |- | Untere Schwelle || 4,0 V || aus der VBus-Spec |- |} Aktuell werden Widerstände aus der E6- und (damit es ein bisschen Mehr Auswahl gibt) E12-Reihe für die Bauteilsuche genutzt. Für die eingegebenen Werte ergibt sich eine schöne Kombination aus der E6-Reihe, die nur drei unterschiedliche Werte benötigt: {| class="wikitable" ! Referenz || Wert |- | R8 || 15 k |- | R5 || 4,7 k |- | R3 || 4,7 k |- | R4 || 2,2 k |- | R2 || 15 k |} Zur Gegenprobe - der Spannungsteiler gibt folgende Spannung aus: <math>(\textrm{8,2 V} - \textrm{1,4 V}) \cdot \frac{\textrm{4,7 k}}{\textrm{4,7 k} + \textrm{15 k}} = \textrm{6,8 V} \cdot \frac{\textrm{4,7}}{\textrm{19,7}} = \textrm{1,62 V}</math> Da ist noch gut Luft zu den Maximal 1,8 V - rechnet man rück, dürfte der Spannungsabfall über den Gleichrichter bis auf 0,65 (für beide Dioden) fallen, um auf eine Eingangsspannung von über 1,8 V am Komparator zu kommen Der Kondensator für den Tiefpass kann übrigens gleich bleiben. Die Grenzfrequenz steigt zwar ein wenig, der Wert ist jedoch weniger kritisch. Daraus ergibt sich folgender Schaltplan: <gallery> Vbuspi_1.2b_assy_sch.png|Schaltplan Version 1.2b </gallery> Die aktualisierte BOM lautet wie folgt: <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> Damit sollte nun der Komparator glücklich sein. Auch in der Simulation in LTspice passen die Schwellen und das Verhalten der Schaltung. Hierzu hatte Stefan folgende Anmerkung: <pre> Nicht gefallen tut mir der C6 von 100pF. Dadurch wird zwar die Referenz stabiler aber die Schwellenumschaltung beim Pegelwechsel wird langsamer. Damit reduziert sich die Störfestigkeit des Eingangssignals. Ich hätte es aber vermutlich auch so gemacht. </pre> Ja, das ist richtig - und auch ich war/bin über den Kondensator nicht so richtig glücklich. Das Bauteil ist meiner Meinung allerdings ein sehr einfacher und effektiver Weg, das beschriebene Problem - besonders im bereits existierenden Design - einfach zu umgehen. Da die Versorgung nicht 100 %ig stabil war, hatte er noch folgenden Ratschlag: <pre> Noch eine Anmerkung zu deiner Kostenreduktion mit dem TS5205 CX533. Ich vermute dass der Ausgangskondensator (C3) nicht passt (ESR zu hoch). LowDrop Regler sind bei zu hohem ESR instabil. Manchmal hilft ein 2ter Kondensator parallel zu C3 (so 10nF bis 100nF) um den Regler stabil zu bekommen. </pre> Was ich versucht habe aber nicht zum gewünschten Erfolg verhalf. Das Problem ist vermutlich eher, dass die Schaltung bei aktivem Optokoppler gänzlich aus den Bulk-Kondensatoren gespeist werden müssen. Da hilft nur mehr Kapazität am Eingang, weswegen als Workaround C5 "aufgedoppelt" werden sollte (Stapeln zweier Kondensatoren). Das ist zwar nicht so richtig schön, aber sollte in den meisten Fällen helfen. Aufgrund der verschiedenen Unzulänglichkeiten - und um den bei manchen Reglern erforderlichen Rückkanal zu haben - gibt es eine verbesserte Version der Hardware: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 5a7201859e124755517bddb1adf0196b0c18c66b 1632 1630 2021-02-26T20:36:25Z Chris 2 Hinweis zu den Hardwareversionen hinzugefügt wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Leiterkarten= Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =Kostenreduzierte Variante/v1.2= Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ==Die Enttäuschung== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers]], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ==Die (vermeintliche) Lösung== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} ==Die Enttäuschung - Teil 2== Stefan schickte eine Mail mit einen sehr guten Verbesserungsvorschlag bzw. vielmehr Hinweis auf Fehler: <pre> Ich würde an deiner Stelle bei der 3,3V Schaltung den Spannungsteiler R8/R5 anpassen. An dessen Eingang können ~7V anliegen womit der OP dann 3,5V an seinem Eingang hat. Das ist bei 3,3V Versorgungsspannung etwas über der Spezifikation des verwendeten OPs. </pre> Das ist absolut richtig, die Spannung ist außerhalb der Spec. Der Fehler hat sich mit an Sicherheit grenzender Wahrscheinlichkeit eingeschlichen, weil beim Neudimensionieren der Schaltung nur die Teile berücksichtigt wurden, die direkt an +3V3 hängen. Schaut man noch etwas genauer ins Datenblatt entdeckt man, dass die Eingänge des LM393 für eine korrekte Funktion einen gewissen Abstand zu V+ haben müssen. Bei der Variante von TI sind das VDD - 1,5 V. Ok, das ist natürlich Mist. Aber beherrschbarer. Im Prinzip müssen nur die Widerstände für die Spannungsteiler neu berechnet werden. Jetzt kann man es sich natürlich einfach machen und die naheliegendsten Werte aus der E24-Reihe nehmen. Selbst für gut ausgestattete Widerstandslager zu Hause würde das eine Bestellung bei den üblichen Verdächtigen bedeuten. Dann hat man meistens noch die vermutlich selten genutzten Wert-Überreste in einer Schublade liegen und das Bestücken ist fehleranfälliger. Uncool. Also warum nicht so lange mit den Bauteilwerten jonglieren, bis es eine gute Kombination gibt? Kann man manuell machen, ist aber eher mühsam. Geht auch mit Excel, ist aber auch nicht das beste Tool dafür. Ob JavaScript so wirklich dafür geeignet ist, sei mal dahingestellt - dafür spricht allerdings, dass mittlerweile fast jedes Endgerät mit Farbdisplay eine passende Laufzeitumgebung installiert hat. Herausgekommen ist dieser [//hobbyelektronik.org/tools/komparator/ schlichte Rechner]. Zahlen eingeben und los geht's: {| class="wikitable" ! Bezeichnung || Wert || Kommentar |- | Versorgungsspannung Komparator || 3,3 V || |- | Maximale Eingangsspannung Komparator || 1,8 V || (3,3 - 1,5) V |- | Maximale Signalspannung || 6,8 V || (8,2 - 1,4) V |- | Obere Schwelle || 4,5 V || aus der VBus-Spec |- | Untere Schwelle || 4,0 V || aus der VBus-Spec |- |} Aktuell werden Widerstände aus der E6- und (damit es ein bisschen Mehr Auswahl gibt) E12-Reihe für die Bauteilsuche genutzt. Für die eingegebenen Werte ergibt sich eine schöne Kombination aus der E6-Reihe, die nur drei unterschiedliche Werte benötigt: {| class="wikitable" ! Referenz || Wert |- | R8 || 15 k |- | R5 || 4,7 k |- | R3 || 4,7 k |- | R4 || 2,2 k |- | R2 || 15 k |} Zur Gegenprobe - der Spannungsteiler gibt folgende Spannung aus: <math>(\textrm{8,2 V} - \textrm{1,4 V}) \cdot \frac{\textrm{4,7 k}}{\textrm{4,7 k} + \textrm{15 k}} = \textrm{6,8 V} \cdot \frac{\textrm{4,7}}{\textrm{19,7}} = \textrm{1,62 V}</math> Da ist noch gut Luft zu den Maximal 1,8 V - rechnet man rück, dürfte der Spannungsabfall über den Gleichrichter bis auf 0,65 (für beide Dioden) fallen, um auf eine Eingangsspannung von über 1,8 V am Komparator zu kommen Der Kondensator für den Tiefpass kann übrigens gleich bleiben. Die Grenzfrequenz steigt zwar ein wenig, der Wert ist jedoch weniger kritisch. Daraus ergibt sich folgender Schaltplan: <gallery> Vbuspi_1.2b_assy_sch.png|Schaltplan Version 1.2b </gallery> Die aktualisierte BOM lautet wie folgt: <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> Damit sollte nun der Komparator glücklich sein. Auch in der Simulation in LTspice passen die Schwellen und das Verhalten der Schaltung. Hierzu hatte Stefan folgende Anmerkung: <pre> Nicht gefallen tut mir der C6 von 100pF. Dadurch wird zwar die Referenz stabiler aber die Schwellenumschaltung beim Pegelwechsel wird langsamer. Damit reduziert sich die Störfestigkeit des Eingangssignals. Ich hätte es aber vermutlich auch so gemacht. </pre> Ja, das ist richtig - und auch ich war/bin über den Kondensator nicht so richtig glücklich. Das Bauteil ist meiner Meinung allerdings ein sehr einfacher und effektiver Weg, das beschriebene Problem - besonders im bereits existierenden Design - einfach zu umgehen. Da die Versorgung nicht 100 %ig stabil war, hatte er noch folgenden Ratschlag: <pre> Noch eine Anmerkung zu deiner Kostenreduktion mit dem TS5205 CX533. Ich vermute dass der Ausgangskondensator (C3) nicht passt (ESR zu hoch). LowDrop Regler sind bei zu hohem ESR instabil. Manchmal hilft ein 2ter Kondensator parallel zu C3 (so 10nF bis 100nF) um den Regler stabil zu bekommen. </pre> Was ich versucht habe aber nicht zum gewünschten Erfolg verhalf. Das Problem ist vermutlich eher, dass die Schaltung bei aktivem Optokoppler gänzlich aus den Bulk-Kondensatoren gespeist werden müssen. Da hilft nur mehr Kapazität am Eingang, weswegen als Workaround C5 "aufgedoppelt" werden sollte (Stapeln zweier Kondensatoren). Das ist zwar nicht so richtig schön, aber sollte in den meisten Fällen helfen. Aufgrund der verschiedenen Unzulänglichkeiten - und um den bei manchen Reglern erforderlichen Rückkanal zu haben - gibt es eine verbesserte Version der Hardware: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 10aec1595318518cb1bdc624d76bf3fa30ceb245 VBus-Decoder/AVR8-Software 0 707 1603 2021-02-09T20:05:38Z Chris 2 Seite erstellt wikitext text/x-wiki {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' Die Software ist in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> =Debug-Ausgabe= [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei <code>%ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml</code> findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. Alternativ kann man auch die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] zu Rate ziehen. =Bekannte Fehler/Macken= [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: * Einstrahlung * Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) * Unbekannt-Felder ** anscheinend immer 0x00 * Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: * RAM-Belegung * Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) * Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Downloads= * [[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] dc36966c372f2409bfdc476d16a7667bc9da1c7a 1612 1603 2021-02-09T20:30:49Z Chris 2 Überschrift hinzugefügt, damit das Inhaltsverzeichnis oben platziert wird wikitext text/x-wiki {{Infobox AVR | Typ = ATmega32 | Takt = 12 | FuseH = CF | FuseL = FF }} ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Integration= Die Software ist in C geschrieben. Über den Befehl Vbus_ProcessChar() kann ein Zeichen von der seriellen Schnittstelle übergeben werden. Im einfachsten Fall kann die ISR-Routine wie folgt aussehen: <source lang="c"> ISR (USART_RXC_vect) { Vbus_ProcessChar(UDR); } </source> Vorher muss noch der UART initialisiert werden (9600 8N1, sei() nicht vergessen!). Die empfangenen und dekodierten Daten werden in der Variable vbus_outdata gespeichert. In dieser Variable muss auch angegeben werden, ob ein Paket gelesen werden soll: <pre> vbus_outdata.update = 1; </pre> Ist ein Paket vollständig angekommen, wird die valid-Eigenschaft auf 1 gesetzt. Im Demo-Code wird nach erfolgreichem Empfang das komplette Datenpaket am UART ausgegeben (bitte nicht an den Regler zurückschicken, sondern möglichst an den PC!): <source lang="c"> int main() { ... while(1) { if(vbus_outdata.valid == 1) { vbus_outdata.valid = 0; VBus_Show_Values(); vbus_outdata.update = 1; } } } </source> =Debug-Ausgabe= [[Bild:Vbus debug.jpg|thumb|Anzeige auf dem Display. die ICs unten und rechts gehören nicht zur Schaltung]] Der Debug in der Software gibt einige Informationen zur Dekodierung auf einem LC-Display aus. Dieser Modus kann in der Datei vbus.h Zeile 35 aktiviert werden (standardmäßig deaktiviert). Über UART würde eine Ausgabe kaum sinn machen, da man durch das langsame Senden den Empfang der Daten verpasst. Zugegebenermaßen: ich habe einen Exoten mit LC7980-Controller und einer Auflösung von 240x40 Pixel verwendet. Die Routinen lassen sich aber halbwegs einfach auf einen anderen Displaycontroller anpassen. Die Ausgabe auf dem Display sieht wie folgt aus: Bei jedem Erhalt eines Sync-Wortes wird "Sync" angezeigt. Wurde der Head empfangen, wird der Displayinhalt gelöscht und folgendes ausgegeben: <pre> D:<Ziel-Adresse> S:<Quell-Adresse> V:<Protokoll-Version> C:<Befehl> F:<Anzahl Frames> X:<Prüfsumme ok|nok> </pre> Danach wird, wenn die Prüfsumme ok ist jedoch das falsche Protokoll angegeben wurde, die Meldung "!V1.0->dropped " ausgegeben. Hat das Paket das "falsche" Adress-Pärchen, wird "Wrong addr->dropped " angezeigt. Kommen diese beiden Meldungen nicht, werden Informationen über die dekodierten Frames ausgegeben: <pre> F<Frame-Index><Prüfsumme ok|nok> </pre> Nachdem alle Frames empfangen wurden, wird ein "AFR" (all frames received) ausgegeben Im Ganzen kann solch eine Ausgabe wie folgt aussehen: <pre> Sync [Display wird geleert] D:0x0010 S:0x7321 V:1 C:0x0100 F:18 X:ok F0ok F1ok F2ok F3ok F4ok F5ok F6ok F7ok F8ok F9nok F10ok F11ok F12ok F13ok F14nok F15ok F16ok F17ok AFR </pre> Gleiches Beispiel mit meinen Testdaten, nur dass hier (im Gegensatz zu den Daten!!) Frame 9 und 14 ungültig sind. ==Zuordnung der Datenfelder== Die Zuordnung der empfangenen Daten kann man relativ einfach zu den entsprechenden Feldern zuordnen. Im der Datei <code>%ProgramFiles%\RESOL\ServiceCenterFull\eclipse\plugins\de.resol.servicecenter.vbus.<Device>\VBusSpecification<Device>.xml</code> findet man alle Zuordnungen der Felder. Achtung: es kann Lücken geben - dadurch sind in meinem Code die "unknown"-Felder entstanden. Alternativ kann man auch die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] zu Rate ziehen. =Bekannte Fehler/Macken= [[Bild:Vbus_putty_vs_rss.png|thumb|Daten meiner Auswertung (links) und die des Resol ServiceCenters]] Folgendes wurde noch nicht getestet/ist unbekannt: * Einstrahlung * Werte hinter der Fehler- & Warnungsmaske (muss ich noch in den XML-Dateien nachlesen) * Unbekannt-Felder ** anscheinend immer 0x00 * Woher kommt der Wochentag bei der Systemzeit Verbesserungswürdig an der Software: * RAM-Belegung * Unterstützung der weiteren Protokolle (Parametrisierung - werde ich aber vermutlich nicht in absehbarer Zeit implementieren) * Es ist nicht ersichtlich, welche Daten durch Prüfsummenfehler ungültig sind =Downloads= * [[Datei:VbusDecode.zip]] Version 0.2beta vom 09.03.2010 ATmega32 @ 12MHz [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] d6e5be7eb6307a178aab6e09643f4e94550ffdec Prozeda-Decoder 0 460 1608 1245 2021-02-09T20:21:59Z Chris 2 Datenstick ausgelagert wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FT2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Einblick in den Regler= Ein Griff in die Zukunft - 11/2017: Im Rahmen der [[Pirozeda]]-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen: <gallery> sungo_sxlplus.JPG | SUNGO SXLplus von außen sungo_sxlplus_ctrl_top.jpg | Controllerboard vorne sungo_sxlplus_ctrl_bot.jpg | Controllerboard hinten sungo_sxlplus_pwr_top.jpg | Leistungsboard vorne sungo_sxlplus_pwr_bot.jpg | Leistungsboard hinten sungo_sxlplus_pwr_port.jpg | Anschluss des Datasticks sungo_sxlplus_pwr_switch.jpg | Schaltmodule </gallery> ==Controllerboard== Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte. Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war. Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt. Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt... ==Leistungsboard== So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen. Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter. Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder. Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können. =[[Prozeda-Decoder/Der Datenstick|Der Datenstick]]= Um den Hauptartikel schlanker zu halten und da sich der Exkurs über den Datenstick als Sackgasse herausgestellt hat, ist dieser Teil des Artikels auf die gleichnamige Unterseite ausgegliedert. (Klick auf die Überschrift) =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 9bbb4ea707f8ef22abfeb75c8cba941df135f716 1610 1608 2021-02-09T20:23:50Z Chris 2 /* Anmerkungen */ Dank erweitert wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FT2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Einblick in den Regler= Ein Griff in die Zukunft - 11/2017: Im Rahmen der [[Pirozeda]]-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen: <gallery> sungo_sxlplus.JPG | SUNGO SXLplus von außen sungo_sxlplus_ctrl_top.jpg | Controllerboard vorne sungo_sxlplus_ctrl_bot.jpg | Controllerboard hinten sungo_sxlplus_pwr_top.jpg | Leistungsboard vorne sungo_sxlplus_pwr_bot.jpg | Leistungsboard hinten sungo_sxlplus_pwr_port.jpg | Anschluss des Datasticks sungo_sxlplus_pwr_switch.jpg | Schaltmodule </gallery> ==Controllerboard== Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte. Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war. Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt. Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt... ==Leistungsboard== So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen. Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter. Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder. Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können. =[[Prozeda-Decoder/Der Datenstick|Der Datenstick]]= Um den Hauptartikel schlanker zu halten und da sich der Exkurs über den Datenstick als Sackgasse herausgestellt hat, ist dieser Teil des Artikels auf die gleichnamige Unterseite ausgegliedert. (Klick auf die Überschrift) =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank, Hans und alle die beteiligt waren für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 32ddf03d3633bfea3142c48514c6b57835ca1163 Prozeda-Decoder/Der Datenstick 0 708 1609 2021-02-09T20:22:13Z Chris 2 Seite erstellt wikitext text/x-wiki Wie bereits im [[Prozeda-Decoder|Hauptartikel]] erwähnt, verbirgt sich im Stick nichts mehr als ein Atmel [http://www.atmel.com/images/doc2225.pdf AT45DB081D] - ein 8 MBit großer Flash-Speicher mit SPI als Interface. Dieser wird über einen 8-poligen Mini-DIN-Stecker mit dem Regler bzw. dem Adapter zum Auslesen am PC verbunden. <gallery> Prozeda_stick.jpg|Der zerlegte Stick Prozeda_buchse.jpg|Buchse am Regler </gallery> {| class="wikitable" ! Pin || Bezeichnung |- | 1 || 17 V |- | 2 || unbekannt |- | 3 || MISO |- | 4 || GND |- | 5 || 3,3 V |- | 6 || MOSI |- | 7 || SCK |- | 8 || !CS |} =Datenformat= Mit der PC-Software lassen sich die Daten vom Logger sowohl als Rohdaten als auch im CSV-Format auf dem PC speichern. Beide Datensätze habe ich bekommen: <pre> aa5540052401ffffffffffffffffff0020205761676e6572202620436f2000000000000000000000000020536f6c617220536f6c6172746563686e696b20... </pre> <pre style="overflow: auto"> ;Datalogging ; Wagner & Co ; ; Solartechnik XXXXXXXXXXXXXXXX ; System-Nr. XXXX ; System-Ver. XXX Datum Uhrzeit Kollektor Speicher unten Speicher oben Rücklaufanh. Rücklaufanh. T T Primär Vorlauf Kaltwasser T Frischwasser Ausgang 1 Ausgang 2 Ausgang 3 Ausgang 4 Ausgang 5 Ausgang 6 Ausgang 7 unused Speicher Speicher Funktion aktiv Funktion aktiv Funktion aktiv Funktion aktiv Durchfluss Zapfung 8 9 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 7 15 11 11 11 11 19 27 09.11.16 18:44:00 -2.100 45.800 48.000 225.100 225.100 225.100 225.100 63.200 46.800 150.700 54.300 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 09.11.16 18:44:00 -2.100 45.700 48.000 228.300 228.300 228.300 228.300 63.300 46.200 200.400 54.400 0.000 0.000 0.000 0.000 100.000 9.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.200 09.11.16 18:44:00 -2.000 45.600 47.900 228.300 228.300 228.300 228.300 63.300 45.800 200.400 54.300 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.600 47.900 231.000 231.000 231.000 231.000 63.300 45.700 225.200 54.300 0.000 0.000 0.000 0.000 100.000 6.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.600 09.11.16 18:44:00 -2.100 45.500 47.900 231.000 231.000 231.000 231.000 63.300 45.500 225.200 54.500 0.000 0.000 0.000 0.000 100.000 7.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.500 09.11.16 18:44:00 -2.000 45.500 47.800 233.300 233.300 233.300 233.300 63.300 45.500 237.600 54.500 0.000 0.000 0.000 0.000 100.000 8.000 0.000 0.000 0 2249 0.100 0.200 0.100 0.200 0.000 -0.400 </pre> Die Systemkennziffern (Seriennummer, System-Nr. und -Version) habe ich durch "X" ersetzt. Die Binärdatei gehört eindeutig zur CSV, nur wie ist der Zusammenhang? Einen Schritt zurück - erstere ist genau 2048 KiB groß, der verwendete Flash-Speicher aber nur 1 MiB. Beim Blick in die Datei: das sieht alles ziemlich hexadezimal aus. Um schnell zum Ziel zu kommen und die Codeeffizient erst einmal egal ist, habe ich PHP verwendet um die Daten umzuwandeln: <source lang="php"> function convert($infile, $outfile) { $if = fopen($infile, "rb"); $of = fopen($outfile, "wb"); while(!feof($if)) { $str = fread($if, 2); fwrite($of, hex2bin($str)); } fclose($if); fclose($of); } </source> Nach ein paar Sekunden konnte ich das Ergebnis in HxD bewundern: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AA 55 40 05 24 01 FF FF FF FF FF FF FF FF FF 00 ªU@.$.ÿÿÿÿÿÿÿÿÿ. 00000010 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 00 Wagner & Co .. 00000020 00 00 00 00 00 00 00 00 00 00 20 53 6F 6C 61 72 .......... Solar 00000030 20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20 XX XX Solartechnik XX 00000040 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX 00000050 20 20 53 79 73 74 65 6D 2D 4E 72 2E 20 20 XX XX System-Nr. XX 00000060 20 53 79 73 74 65 6D 2D 56 65 72 2E 20 20 XX XX System-Ver. XX ... </pre> [[Prozeda-Decoder/Flashimage16|mehr Daten]] Das sieht doch gut aus! ==Speichersegmente== Die nun sichtbaren Daten erzeugen den Eindruck von 3 Datenbereichen: {| class="wikitable" ! Start-Adresse || Ende-Adresse || Länge || Inhalt |- | 0x00000 || 0x0006F || 0x0006F || Systeminfo |- | 0x00200 || 0x0043F || 0x00240 || Spaltenbeschreibung |- | 0x00500 || 0xFFFFF || 0xFFB00 || Loggingdaten |} ==Systeminfo== Die ersten beiden Byte auf dem Flash lauten 0xAA 0x55, die schon beim Initialisieren des Sticks geschrieben werden. Gleiches gilt für das dritte Byte (Adresse 0x00002), das vermutlich das Logging-Intervall repräsentiert. Leider konnte ich das bis jetzt noch nicht so richtig nachvollziehen. Ab Offset 0x00010 befindet sich der Herstellername der Solaranlage. Am Anschluss - ab Offset 0x0003E steht die 18-stellige Seriennummer und ab 0x00050 die Systemnummer, wobei der eigentliche Wert bei 0x0005E mit Länge 2 liegt. Gleiches gilt für die Systemversion, die ab Offset 0x00060 beschrieben und der eigentliche Wert bei 0x0006E - ebenfalls mit Länge 2 liegt. Die beiden letzteren Werte für letztere Bezeichner sind binär Little-Endian abgespeichert, aus 0x12 0x34 würde also 0x3412 bzw. 13330 werden. ==Spaltenbeschreibung== Die Spaltenbeschreibungen sind wie folgt aufgebaut: 16 Zeichen lang, 15 davon sind NULL-terminierte ASCII-Strings gefolgt von einem weiteren Zeichen: <pre> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... 00000200 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 Datum .. 00000210 20 20 20 55 68 72 7A 65 69 74 20 20 20 20 00 09 Uhrzeit .. 00000220 20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 00 10 Sekunden ...... 00000230 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 00 01 Kollektor .. 00000240 20 20 53 70 65 69 63 68 65 72 20 B9 20 20 00 01 Speicher ¹ .. ... </pre> Eine Besonderheit stellen offenbar die ASCII-Zeichen 0xB9 und 0xB3 dar - diese werden beim Auslesen nach "unten" und "oben" übersetzt. Dieses letzte Zeichen spiegelt sich in der Zeile nach den Spaltenköpfen in der CSV-Datei wider. Nach genauerer Betrachtung ergibt sich folgende (mutmaßliche) Zuordnung: {| class="wikitable" ! Wert (Hex) || Datentyp || Länge |- | 00 || Dummy || 2? |- | 01 || Temperatur || 2 |- | 07 || Speicher || 4? |- | 08 || Datum || 2 |- | 09 || Uhrzeit || 2 |- | 0A || Ausgang || 1 |- | 0D || Fehler || 1? |- | 0E || Fehler || 2? |- | 0F || Speicher || 2? |- | 10 || Sekunden || 2 |- | 13 || Durchfluss || 2 |- | 1B || Zapfung || 2 |} Zur Länge später mehr. ==Loggingdaten== Ab Adresse 0x00500 wird es interessant, hier befindet sich die Payload. Als "Trick" um die Datenlänge besser ermitteln zu können hat sich bewährt, die Anzeigebreite des Hex-Editors auf Fenstergröße anpassen zu lassen und dann die Breite des Fensters zu variieren. Dadurch lassen sich Wiederholungen besser erkennen. So bei 64 Byte Breite: <pre style="overflow: auto"> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C ... 00000500 55 04 64 04 2F 00 EB FF CA 01 E0 01 CB 08 CB 08 CB 08 CB 08 78 02 D4 01 E3 05 1F 02 00 00 00 00 64 08 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d./.ëÿÊ.à.Ë.Ë.Ë.Ë.x.Ô.ã.......d....UU.......É.............üÿ.. 00000540 55 04 64 04 30 00 EB FF C9 01 E0 01 EB 08 EB 08 EB 08 EB 08 79 02 CE 01 D4 07 20 02 00 00 00 00 64 09 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FE FF 00 00 U.d.0.ëÿÉ.à.ë.ë.ë.ë.y.Î.Ô. .....d....UU.......É.............þÿ.. 00000580 55 04 64 04 31 00 EC FF C8 01 DF 01 EB 08 EB 08 EB 08 EB 08 79 02 CA 01 D4 07 1F 02 00 00 00 00 64 07 00 00 00 55 55 00 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.1.ìÿÈ.ß.ë.ë.ë.ë.y.Ê.Ô.......d....UU.......É.............ûÿ.. 000005C0 55 04 64 04 32 00 EC FF C8 01 DF 01 06 09 06 09 06 09 06 09 79 02 C9 01 CC 08 1F 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.2.ìÿÈ.ß.........y.É.Ì.......d....UU.......É.............úÿ.. 00000600 55 04 64 04 33 00 EB FF C7 01 DF 01 06 09 06 09 06 09 06 09 79 02 C7 01 CC 08 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.3.ëÿÇ.ß.........y.Ç.Ì.!.....d....UU.......É.............ûÿ.. 00000640 55 04 64 04 34 00 EC FF C7 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C7 01 48 09 21 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.4.ìÿÇ.Þ.........y.Ç.H.!.....d....UU.......É.............üÿ.. 00000680 55 04 64 04 35 00 EC FF C6 01 DE 01 1D 09 1D 09 1D 09 1D 09 79 02 C8 01 48 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.5.ìÿÆ.Þ.........y.È.H. .....d....UU.......É.............ûÿ.. 000006C0 55 04 64 04 36 00 EC FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C8 01 86 09 20 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.6.ìÿÆ.Þ.2.2.2.2.y.È.?. .....d....UU.......É.............ûÿ.. 00000700 55 04 64 04 37 00 EB FF C6 01 DE 01 32 09 32 09 32 09 32 09 79 02 C7 01 A5 09 21 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.d.7.ëÿÆ.Þ.2.2.2.2.y.Ç.¥.!.....d....UU.......É.............úÿ.. 00000740 55 04 64 04 38 00 EB FF C5 01 DE 01 45 09 45 09 45 09 45 09 79 02 C7 01 B4 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.8.ëÿÅ.Þ.E.E.E.E.y.Ç.´.!.....d....UU.......É.............ûÿ.. 00000780 55 04 64 04 39 00 EB FF C5 01 DD 01 45 09 45 09 45 09 45 09 79 02 C6 01 BC 09 22 02 00 00 00 00 64 08 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FC FF 00 00 U.d.9.ëÿÅ.Ý.E.E.E.E.y.Æ.¼.".....d....UU.......É.............üÿ.. 000007C0 55 04 64 04 3A 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 78 02 C6 01 C0 09 23 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.d.:.ëÿÅ.Ý.T.T.T.T.x.Æ.À.#.....d....UU.......É.............ûÿ.. 00000800 55 04 65 04 00 00 EB FF C5 01 DD 01 54 09 54 09 54 09 54 09 7A 02 C7 01 C2 09 23 02 00 00 00 00 64 06 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FA FF 00 00 U.e...ëÿÅ.Ý.T.T.T.T.z.Ç.Â.#.....d....UU.......É.............úÿ.. 00000840 55 04 65 04 01 00 EB FF C4 01 DD 01 62 09 62 09 62 09 62 09 79 02 C7 01 C3 09 21 02 00 00 00 00 64 07 00 00 00 55 55 10 00 00 00 00 00 00 C9 08 00 00 01 00 02 00 01 00 02 00 00 00 FB FF 00 00 U.e...ëÿÄ.Ý.b.b.b.b.y.Ç.Ã.!.....d....UU.......É.............ûÿ.. ... </pre> Zieht man die Spaltenbeschreibungen zu Rate, müssen die ersten Bytes das Datum und die Uhrzeit sein. Und tatsächlich, bei Offset 0x04 sieht man, dass der Wert hochzählt. Angekommen bei 0x3A nullt der Wert und an Offset 0x02 wird hochgezählt. 0x3A ist allerdings nicht 59, sondern 58. Vielleicht eine leichte Asynchronität zwischen Uhr und Aufzeichnung? Scrollt man weiter nach unten, ändern sich auch die Bytes davor. Interessant ist hierbei, dass sich die geraden Bytes öfter ändern als die ungeraden. Oder: die "ersteren" scheinen das kleine Ende der entsprechenden Zahl zu repräsentieren. Unser System scheint Little Endian zu verwenden. Interessant ist auch, dass bei Offset 0x05 konsequent eine Null steht. Wenn es sich tatsächlich um Sekunden handelt, warum haben die Entwickler hier sinnlos Platz verschwendet? Ungeduldig wie ich bin (das da vorne _muss_ ein Timestamp sein), habe ich mir die nächsten Bytes angesehen. Offset 0x06 eiert um 0xEB herum, Offset 0x07 ist für länger konstant 0xFF, "schnappt" aber irgendwann auf 0x00 um. Da es unwahrscheinlich ist, dass sich ein Wert sehr stark ändert, tippe ich 0xFFEB in den Taschenrechner ein, stelle ihn auf Word-Breite ein und bekomme direkt -21 ausgespuckt (der Windows-Taschenrechner verwendet signed Datentypen). Ein Blick nach oben in die Daten der CSV-Datei verrät -2,1 °C. Die nächsten zwei Byte (bei Offset 0x08 und 0x09) lauten 0xCA 0x01, der Taschenrechner macht aus 0x01CA die dezimale Entsprechung 458. Die CSV-Tabelle sagt in der Spalte der ersten Zeile 45,8 °C. Das war einfach! Um die Daten besser untersuchen zu können, habe ich das Swiss-Army-Knife aller BWLer und das Hacking-Tool schlechthin verwendet: Excel. Mit Den Spaltenköpfen und der ersten Logzeile aus der CSV-Datei und der ersten Zeile (Hex-Codiert) aus der Binärdatei mache ich mich ans Werk. Spalte F dient dazu den Offset für einen Wert vorzugeben, Spalte G bestimmt die Länge der in Spalte H separierten Hex-Werte. In Spalte I werden die ersten beiden Teile getauscht (ok, das funktioniert nur für maximal 2 Byte lange Werte) und von Hexadezimal nach Dezimal umgerechnet. In Spalte J wird von Unsigned nach Signed umgewandelt (was allerdings nur für 2 Byte lange Datensätze funktioniert). Nach etwas Schätzen, Daten vorwärts und rückwärts durchgehen, ergab sich die Tabelle für die Spaltenbeschreibung von oben. Bei der Länge der Datenfelder für Fehler bin ich mir nicht 100 % sicher aber es sieht sehr plausibel aus. Zurück zum Datum und der Uhrzeit. Da steht bei dem Satz 1109 und 1124, was dem 09.11.2016 und 18:44 entsprechen soll. Jetzt kann man lang überlegen, mit dem Tag seit Datum X rechnen oder einfach einen Strich zwischen 11 und 09 packen. Eine Jahresangabe sucht man vergebens. Bei der Uhrzeit ist es naheliegend, die Sekunden oder Minuten seit Mitternacht zu zählen - also einfach mal geteilt durch 60, ergibt: 18,73 - 18 Uhr passt, 0,73 entspricht den 44 Minuten. Haken dran. Die Sekunden werden von der PC-Software interessanterweise nicht ausgegeben, durch die Spaltenbeschreibung im Flash muss die dritte Spalte aber den Sekunden-Anteil repräsentieren. Ein Datensatz aufgedröselt sieht dann wie folgt aus: <gallery> Datei:Prozeda_Datenformat.png </gallery> =Kommunikation mit dem Datastick= Wie die Daten im Speicher aussehen ist nun bekannt, aber wie kommen sie drauf? Frank war so freundlich und hat mir Traces geschickt. Leider zunächst nur Exports, in denen ich das genaue Timing und "alles andere" nicht sehen konnte. Wie André Lampe in seinem 33C3-Vortrag "[https://media.ccc.de/v/33c3-8237-es_sind_die_kleinen_dinge_im_leben Es sind die kleinen Dinge im Leben]" sagte: Rohdaten sind geil. Später habe ich noch vollständige Datensätze bzw. die Rohdaten bekommen. Leider kann/möchte ich diese an dieser Stelle zum aktuellen Zeitpunkt nicht veröffentlichen, da es momentan keinen Weg gibt, die Dateistruktur von Saleae Logic zu verändern und ich somit die im Trace vorkommenden Seriennummern nicht entfernen kann. Die Konfiguration für den SPI kann man größtenteils aus dem Datenblatt des Flashs ermitteln: * MSB first * 8 Bit je Datenwort * SPI-Mode 0 oder 3 * CS low-aktiv Im vorliegenden Fall wird Mode 0 verwendet. Der Export des SPI-Analyzers aus Logic sieht wie folgt aus: <pre> Time [s],Packet ID,MOSI,MISO 0.941889000000000,0,0xE8,0x00 0.941953000000000,0,0x00,0x00 0.942017416666667,0,0x00,0x00 0.942081583333333,0,0x00,0x00 0.942149166666667,0,0xAA,0x00 0.942213333333333,0,0xAA,0x00 0.942277583333333,0,0xAA,0x00 0.942341750000000,0,0xAA,0x00 0.942409833333333,0,0xAA,0x00 0.943974750000000,1,0xE8,0x00 0.944038833333333,1,0x00,0x00 0.944103083333333,1,0x00,0x00 0.944169166666667,1,0x00,0x00 </pre> ...und ist damit ziemlich unleserlich. Neben den übertragenen Daten lässt sich auch die Bitrate grob abschätzen - jede Zeile entspricht einem übertragenen Byte und dauert im ersten Paket im Schnitt 65,1 µs. Mit 8 Bit je Datenwort kann ein Bit höchstens 8,138 µs dauern. Die Bitrate muss also etwas höher als 123 kHz sein, abhängig davon wie groß die Pausen zwischen den Bytes sind. Die Wahrheit sieht natürlich etwas anders aus <gallery> Datei:Prozeda_bitrate.png| </gallery> 233 kHz Clock-Frequenz und etwas um 32 µs zwischen den Bytes. ==Traces lesbarer machen== Die Exporte von Logic sind gut, aber nicht für jede Anwendung. Um die übertragenen Daten zu verstehen ist mir das Timing nicht ganz so wichtig, aber der Inhalt der Nachrichten muss gut lesbar sein. Also habe ich ein kleines Programm geschrieben (siehe unten), um die Pakete zu komprimieren, was dann wie folgt aussieht: {| class="wikitable" ! Time || Packet || Sent data || Received data |- | 0,941889000000000 || 0 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | 0,943974750000000 || 1 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 00 |- | colspan="4" | ... |- | 7,979580416666670 || 14 || E8 00 00 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 AA |- | 7,981663083333330 || 15 || E8 00 00 01 AA AA AA AA AA || 00 00 00 00 00 00 00 00 55 |- | 7,983659916666670 || 16 || E8 00 00 02 AA AA AA AA AA || 00 00 00 00 00 00 00 00 01 |- | 8,011756000000000 || 17 || E8 00 0A 00 AA AA AA AA AA || 00 00 00 00 00 00 00 00 FF |- | 8,014754250000000 || 18 || E8 00 00 00 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ... || ... |- | 8,051748750000000 || 19 || 82 00 00 00 AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 61 67 6E 65 72 20 26 20 43 6F 20 00 ... || ... |} Zugleich wird der Timestamp angepasst, damit die Datei direkt von Excel eingelesen werden kann. Die Spalten sind zudem per Tab getrennt, was beim Import etwas angenehmer sein kann Schaut man im Datenblatt nach den verschiedenen Befehlen, findet man unter 0xE8 "Continuous Array Read" und unter 0x82 "Main Memory Page Program through Buffer 1". Tabelle 4 im Dokument den Aufbau der zu den Befehlen gehörenden Sequenzen. Demnach wird in Paket 0 der Zeiger auf Page 0 und Buffer Address Bit 0 gesetzt und ein Byte gelesen, welches mit 0x00 beantwortet wird. Ignoriert man Paket 1 geschieht dies im Sekundentakt (nicht oben gezeigt), bis in Paket 14 0xAA zurückgegeben wird. Jetzt kann man die Kommunikation schon ziemlich gut verfolgen, allerdings: warum sollte man es sich unnötig schwer machen, wenn man den PC für sich arbeiten lassen kann? Also habe ich das Programm zum Komprimieren der Daten erweitert - es kann auch die im Protokoll verwendeten Befehle interpretieren: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 0,941889000000000 || 0 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 0,943974750000000 || 1 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | colspan="7" | ... |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 ... |} ==Kommunikation zum Speicher== ===Erkennung=== Um den Datastick zu erkennen, wird im Sekundentakt versucht die Adresse 0x00000 zu lesen. Beinhaltet diese den Wert 0x00 wird davon ausgegangen, dass kein Stick gesteckt ist (keine Antwort). Wird das "Magic Byte" 0xAA erkannt, wird anschließend Adresse 0x00001 gelesen, die bei einem korrekt initialisierten Stick 0x55 beinhaltet: {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |} Diese Erkennung läuft auch nachdem ein Stick erfolgreich erkannt wurde. Es ist der einfachste Weg, ein Entfernen des Loggers festzustellen, auch wenn es über die anderen Kommunikationsinhalte ebenfalls möglich wäre. Anschließend gibt es eine Fallunterscheidung: Entweder der Stick kommt frisch initialisiert vom PC oder er war schon einmal an der Anlage. Dazu wird an Adresse 0x000500 geprüft, ob 0xFF (mutmaßlich unbeschrieben) oder ein anderer Wert steht. Handelt es sich um ersteren, wird von einem frisch initialisierten Stick ausgegangen. ====Frisch initialisierter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 5,970892583333330 || 11 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,974197916666670 || 12 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 6,976281000000000 || 13 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 7,979580416666670 || 14 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 7,981663083333330 || 15 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 7,983659916666670 || 16 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 01 |- | 8,011756000000000 || 17 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || FF |- | 8,014754250000000 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 8,051748750000000 || 19 || 82H Write through Buff1 || 0x0000 || 0x000000 ... 0x0000FF || 256 || AA 55 01 05 24 01 FF FF FF FF FF FF FF FF FF 00 20 20 57 ... |- | 8,095399500000000 || 20 || 82H Write through Buff1 || 0x0002 || 0x000200 ... 0x0002FF || 256 || 20 20 20 20 44 61 74 75 6D 20 20 20 20 20 00 08 20 20 20 ... |- | 8,139579833333330 || 21 || 82H Write through Buff1 || 0x0003 || 0x000300 ... 0x0003FF || 256 || 20 20 41 75 73 67 61 6E 67 20 33 20 20 20 00 0A 20 20 41 ... |- | 8,182810250000000 || 22 || 82H Write through Buff1 || 0x0004 || 0x000400 ... 0x0004FF || 256 || 46 75 6E 6B 74 69 6F 6E 20 61 6B 74 69 76 00 0B 20 20 44 ... |- | 8,224643666666670 || 23 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,226721500000000 || 24 || E8H Cont Array Read || 0x0000 || 0x000003 ... 0x000003 || 1 || 05 |- | 8,229152833333330 || 25 || 81H Erase Page || 0x0005 || 0x000500 ... 0x0005FF || 0 |- | 8,239133916666670 || 26 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ... |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 9,156107750000000 || 29 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,158207083333330 || 30 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 9,160199750000000 || 31 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 ... |} In diesem Fall steht an Adresse 0x000500 der Wert 0xFF (Paket 17), was auf noch nicht vorhandene Loggingdaten deutet. In Paket 18 wird augenscheinlich geprüft, ob Kopfdaten vorhanden sind, anschließend werden die Systeminfo (Paket 19) und die Spaltenbeschreibungen (Paket 20, 21 und 22) geschrieben. Die Bedeutung der zusätzlich geschriebenen Bytes (0x05 0x24 0x01) hat sich mir leider noch nicht erschlossen. Warum Byte 0x000003 hier noch einmal und vor allem zweimal (Paket 23 und 24) abgefragt wird, ist mir ebenfalls etwas rätselhaft. Ab Paket 25 beginnt der normale Schreibzyklus (siehe weiter unten). ====Bereits verwendeter Stick==== {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,586632916666670 || 17 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,592280083333330 || 18 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 9,594365416666670 || 19 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || 00 |- | 10,597658333333300 || 20 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 10,599741083333300 || 21 || E8H Cont Array Read || 0x0000 || 0x000001 ... 0x000001 || 1 || 55 |- | 10,601737750000000 || 22 || E8H Cont Array Read || 0x0000 || 0x000002 ... 0x000002 || 1 || 0F |- | 10,629873166666700 || 23 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x000500 || 1 || 6F |- | colspan="7" | Gleicher Lesevorgang und Antwort in Paket 24 ... 50 für die Adressen 0x000540, 0x000580, 0x0005C0, 0x000600, 0x000640, 0x000680, 0x0006C0, 0x000700, 0x000740, 0x000780, 0x0007C0, 0x000800, 0x000840, 0x000880, 0x0008C0, 0x000900, 0x000940, 0x000980, 0x0009C0, 0x000A00, 0x000A40, 0x000A80, 0x000AC0, 0x000B00, 0x000B40, 0x000B80, 0x000BC0 |- | 10,692716666666700 || 51 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000C00 || 1 || 6F |- | 10,694810333333300 || 52 || E8H Cont Array Read || 0x000C || 0x000C40 ... 0x000C40 || 1 || FF |- | 10,696810750000000 || 53 || E8H Cont Array Read || 0x0000 || 0x000000 ... 0x000000 || 1 || AA |- | 11,599035166666700 || 54 || E8H Cont Array Read || 0x000C || 0x000C00 ... 0x000CFF || 256 || 6F 00 46 04 33 00 24 00 B0 01 D3 01 C4 09 C4 09 C4 09 C4 ... |} Nach dem Lesen der Kopfdaten wird Adresse 0x000500, also der Beginn der Loggingdaten angesprungen und ein Byte gelesen (Paket 23). Ist dieses nicht 0xFF, wird so lange um 64 Byte weitergesprungen (Paket 24 ... 51), bis der erste nicht vorhandene Datensatz mit 0xFF am Anfang gefunden wird (Paket 53). An dieser Stelle kann der Schreibzyklus begonnen werden. ===Schreibzyklus=== Das Schreiben der Daten hätte ich mir eigenwilliger nicht ausmalen können. Aufgrund der Gegebenheiten ging ich von zwei Möglichkeiten aus: * Im Regler werden 4 Einträge gecached und anschließend als komplette Page geschrieben * Jeder Eintrag wird einzeln geschrieben und dabei der Pointer auf die jeweilige Adresse gesetzt Stattdessen ist die Vorgehensweise wie folgt: # Prüfen ob es der nächste zu schreibende Satz der letzte innerhalb der aktuellen Page ist und wenn ja: nächste Page löschen # Aktuelle Page auslesen # Aktuelle Page mit angehängten Daten wieder schreiben Die folgende Tabelle ist leider etwas groß, aber hier benötigt man zum Verständnis die gelesenen/geschriebenen Daten. Zum besseren Übersicht habe ich die zyklischen Abfragen zur Erkennung des Sticks entfernt. {| class="wikitable" ! Time || Packet || Opcode || Page || Address from/to || Data length || Data |- | 8,980954250000000 || 27 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,018144083333330 || 28 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 9,991345666666670 || 32 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,028507166666700 || 33 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 10,994477083333300 || 37 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 11,031559916666700 || 38 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,001553583333300 || 42 || 81H Erase Page || 0x0006 || 0x000C00 ... 0x000CFF || 0 || |- | 12,012532583333300 || 43 || E8H Cont Array Read || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 12,049725916666700 || 44 || 82H Write through Buff1 || 0x0005 || 0x000500 ... 0x0005FF || 256 || 6F 00 45 04 29 00 23 00 AD 01 D8 01 C4 09 C4 09 C4 09 C4 09 42 02 3D 01 C4 09 C4 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2A 00 57 00 B6 01 DC 01 CB 08 CB 08 CB 08 CB 08 31 02 A0 01 E3 05 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2B 00 51 00 B5 01 DC 01 EB 08 EB 08 EB 08 EB 08 38 02 6D 01 D4 07 C3 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 6F 00 45 04 2C 00 4C 00 B4 01 DB 01 EB 08 EB 08 EB 08 EB 08 3D 02 55 01 D4 07 C2 01 00 00 00 00 00 00 00 00 00 55 55 00 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 |- | 13,007502916666700 || 48 || E8H Cont Array Read || 0x0006 || 0x000600 ... 0x0006FF || 256 || FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |- | 13,044694416666700 || 49 || 82H Write through Buff1 || 0x0006 || 0x000600 ... 0x0006FF || 256 || 6F 00 45 04 2D 00 47 00 B3 01 DB 01 06 09 06 09 06 09 06 09 3F 02 47 01 CC 08 C2 01 00 00 00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00 F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |} Das ist auch schon so ziemlich alles. Erwähnenswert ist an dieser Stelle noch, dass das Logging-Intervall am Regler während der Laufzeit verändert werden kann. In diesem Fall wird die erste Page neu geschrieben. =Flash-Emulator= Nun könnte man einfach dauerhaft mit eingestecktem Stick mitschnüffeln und die Daten so extrahieren. Leider hört der Solarregler (wahrscheinlich) mit dem Logging auf, wenn der Speicher voll ist. Besser ist da eine Lösung, die man anstecken und vergessen kann. Eine Möglichkeit wäre, den SPI-Flash über Multiplexer an einen Mikrocontroller (oder direkt den SBC) zu hängen und immer wieder auszulesen. Geht, ist aber unnötig viel Aufwand und irgendwann, in 100 Jahren ist der Speicher totgeschrieben. Die meisten Mikrocontroller besitzen einen SPI-Controller, der auch Slave kann. Mit ein bisschen Software lässt sich doch sicher der Speicher emulieren. Der komplette Befehlssatz ist nicht nötig, genauso wenig muss man den kompletten Speicherplatz des Originalbausteins vorhalten. Also habe ich mir also einen ATmega328P (anfänglich ein ATmega8, der aufgrund der 3,3 V allerdings nicht stabil lief) auf ein Breadboard gesteckt und losgelegt - bzw. erst einmal blöd aus der Wäsche geschaut. Zwar wird der Slave-Select-Pin zum aktivieren des SPI-Moduls verwendet, aber es gibt (zumindest beim ATmega8) keinen direkt assoziierten Interrupt auf Kommunikationsstart. Der wird aber zwingend benötigt, da man zur Synchronisation des Protokolls wissen muss, wann ein Paket angefangen hat (zurücksetzen des Byte-Zählers). Ungläubig und sehr irritiert habe ich beim ATmega8 Slave Select mit INT0 verbunden. Beim ATmega328P ist dies nicht notwendig, da dieser über Pin Change Interrupts verfügt, die auf nahezu allen Port-Pins verfügbar sind. Für die Flash-Emulation werden also zwei Interrupts benötigt: SPI_STC (Serial Transfer Complete) und PCINT0 (dem der Slave-Select-Pin zugeordnet ist). Der Programmablauf ist grob wie folgt: Bei fallender Flanke am Slave Select wird, neben dem völlig autark ablaufenden Aktivieren des SPI-Moduls, der Byte-Zähler und der Op-Code zurückgesetzt und das SPDR-Datenregister mit 0x00 vorgeladen. Zusätzlich wird ein Busy-Flag gesetzt um - wenn die Firmware weiter wächst - Aufgaben niedrigerer Prioritäten zurückzustellen. Bei steigender Flanke am Slave Select wird geprüft, welche Aktion im letzten Paket angefordert wurde, was vor allem beim Löschen der Page oder nach dem Schreiben der Loggingdaten - auf die wir es schließlich abgesehen haben - wichtig ist. Im Serial SPI_STC-Interrupt passiert die eigentliche Arbeit: Wird ein Byte über SPI empfangen, schlägt es hier auf. Dank der Variable spi_bytenum weiß das Programm, wo es sich innerhalb des Pakets befindet. Folglich wird das erste Byte in die Variable für den Op-Code geladen, die nächsten drei Byte landen im Adresszähler. Um nicht unnötig Laufzeit zu verschwenden (Interrupt-Zeit ist als "teuer" zu betrachten), habe ich für die Behandlung der Adresse einen Trick (wenn man es so nennen will) angewandt: Der Wert ist 20 bzw. 21 Bit breit. Der nächsthöhere Standardtyp wäre uint32_t, der bei Rechenoperationen jedoch relativ viel Speicher frisst - schließlich handelt es sich um eine 8-Bit-CPU. Da größtenteils eh nur die unteren 16 Bit der Adresse wichtig sind, habe ich eine Union (also eine Verschmelzung mehrerer Datentypen) erstellt, die die Adresse etwas angenehmer speichern lässt: <source lang="c"> volatile union { struct { uint16_t lower; uint8_t upper; } val24; uint8_t val8[3]; } flash_address; </source> Das Schreiben der Werte sieht zwar etwas ungewöhnlich aus, orientiert die Bytes allerdings gleich richtig herum an und berücksichtigt auch den Offset von spi_bytenum (die Adresse kommt für spi_bytenum > 0 und < 4): <source lang="c"> flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; </source> Im Anschluss sind wir schon eine Ebene höher: Für den Op-Code 0xE8 (Read Continuous Array) wird es nach dem 7. Byte interessant, bei Write through Buffer 1 ab dem 4. Byte, was dann in etwa wie folgt aussieht: <source lang="c"> ISR(SPI_STC_vect) { IOPIN_H(DBGO); uint8_t d = SPDR; if(spi_bytenum == 0) { // byte 0 in transfer is the opcode SPDR = 0x00; flash_opcode = (Flash_Opcode_t)d; } else if(spi_bytenum < 4) { SPDR = 0x00; // byte 1 ... 3 are address bytes flash_address.val8[sizeof(flash_address) - spi_bytenum] = d; if(spi_bytenum == 3) { // command completely received, now do what needs to be done //uart_debug_write("%2x:%4x", flash_opcode, flash_address.val24.lower); } } else if(flash_opcode == Flash_Opcode_ReadContArray && spi_bytenum >= 7) { // when reading from the flash, we have to start to transmit // the data already one byte earlier due to delay of MISO if(flash_address.val24.lower <= 0x0003) { // hello bytes SPDR = flash_data_hello[flash_address.val24.lower & 0x03]; } else if(flash_address.val24.lower >= 0x0500) { // logging data section SPDR = flash_data_log[flash_address.val24.lower & 0xFF]; } flash_address.val24.lower++; } else if(flash_opcode == Flash_Opcode_WriteBuff1 && spi_bytenum >= 4) { if(flash_address.val24.lower >= 0x0500) { flash_data_log[flash_address.val24.lower & 0xFF] = d; } flash_address.val24.lower++; } else { // when there's no specific handler for the transmission, reply 0x00 SPDR = 0x00; } // byte number is only important for the first n bytes, after that // there are anyway only data bytes (which are handled separately) if(spi_bytenum < 0xFF) spi_bytenum++; IOPIN_L(DBGO); } ISR(PCINT0_vect) { if(IOPIN_V(SPI_SS) == 0) { spi_bytenum = 0; flash_opcode = 0; // preload SPI data register SPDR = 0x00; trx_flags |= TrxFlags_SpiBusy; } //... } </source> Um die Laufzeit im Blick zu haben, wird zusätzlich ein Debug-Pin zu Beginn des Interrupts auf High und am Ende auf Low gesetzt. Wenn ich mich richtig erinnere, waren es bei 8 MHz CPU-Takt um die 8 µs, also reichlich Luft zu den knapp 30 µs, die zur Verfügung stehen. Allerdings muss dazu gesagt werden, dass in dem Codeschnipsel das Schreiben der Daten in den RAM noch nicht implementiert ist. [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] c1a574fa9851b56b70b918baf817bc62c6f8ee3b Hauptseite 0 1 1611 1579 2021-02-09T20:29:28Z Chris 2 /* Neues & Änderungen */ ein kleines Update und Links korrigiert wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *09.02.2020 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> c4740b387940837c48a07b87ae2065671749ef65 1619 1611 2021-02-09T21:34:09Z Chris 2 /* Neues & Änderungen */ Das mit dem Jahr üben wir nochmal... wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> 0dfd078aaa48bfb9ded3fc1adb85ce3f26b165de 1635 1619 2021-02-26T20:48:51Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *26.02.2021 Und noch ein Update für den VBus-Decoder: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]] und [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> 32289fb2df36ac01e14b9477af05eb197baab06a 1639 1635 2021-02-26T20:57:42Z Chris 2 /* Neues & Änderungen */ Protokoll-Analysator hinzugefügt wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *26.02.2021 Und noch ein Update für den VBus-Decoder: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]] und [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]], sowie einem einfachen [[VBus-Decoder#Protokoll-Analysator|Protokoll-Analysator]] *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> 62fc0f80225c9ebce400763cbbeb2922f5b62f60 Pirozeda 0 487 1621 1392 2021-02-22T21:41:56Z Chris 2 GitHub-Link hinzugefügt wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht entweder über <code>sudo raspi-config</code> (keine Konsole aber UART aktiv) oder in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. ===Vor Pirozeda 0.4=== Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ===Ab Pirozeda 0.4=== Pirozeda ab 0.4 verwendet Python 3. Dementsprechend müssen die Module für die neuere Plattform installiert werden. Für JSON-RPC wird nun eine andere Lib verwendet, die zugleich "Werkzeug" als Webserver verwendet: <source lang="shell"> sudo python3 -m pip install json-rpc werkzeug pyserial </source> Auch hier kann über <code>miniterm</code> geprüft werden, ob Daten ankommen. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. ===Vor Pirozeda 0.4=== Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ===Ab Pirozeda 0.4=== Ab Pirozeda 0.4 kann das Script als [http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/ Service] ausgeführt werden. Das entsprechende Script ist für die Verwendung in <code>/home/pi/pirozeda</code> vorbereitet und kann einfach wie folgt installiert werden: <source lang="shell"> sudo chmod +x pirozeda.py sudo cp pirozeda.sh /etc/init.d sudo chmod +x /etc/init.d/pirozeda.sh sudo update-rc.d pirozeda.sh defaults sudo /etc/init.d/pirozeda.sh start </source> Wer Pirozeda woanders installieren möchte, kann das Shellscript jederzeit entsprechend anpassen. Auch die Verwendung von cron ist natürlich weiterhin möglich, allerdings muss nun python3 verwendet werden. Update 21.04.2019: <code>pirozeda.py</code> muss für die Verwendung der Shell-Datei ebenfalls als ausführbar markiert sein. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= ==Vor Pirozeda 0.4== [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Ab Pirozeda 0.4== [[Datei:Pirozeda rpi.zip]] enthält: * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) === 2019-03-30: Version 0.4 === * Umstellung Auf Python 3 * Script kann nun als Service verwendet werden * Fehlerkorrektur Anzeige von Volumenstrom * Mehr Informationen von der Firmware (Version/Build/Reglerversion/...) Ich habe leider keine Vergleichsdaten aber mir scheint die CPU-Last auf dem Pi bei aktivem Frontend sehr hoch, kann das jemand bestätigen? =Git= Das Projekt liegt auch bei GitHub: https://github.com/chris-heo/pirozeda [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] bffa69249f42df0661eb2461fe402d1f8b85d520 1622 1621 2021-02-22T21:43:35Z Chris 2 GitHub-Link: Weiter oben ist besser wikitext text/x-wiki [[Datei:pirozeda_gehaeuse.jpg|thumb|Fertig aufgebauter Pirozeda (Foto von Hans)]] "Geht das auch direkt mit dem Raspberry Pi?" War eine Anfrage, die ich nun schon ein paar mal bekommen habe. Es besteht also Interesse. =Raspberry Pi als SPI-Slave= ==Bitbanging== Vom [[Prozeda-Decoder]] weiß ich, dass der SPI mit etwa 250 kHz läuft, was nicht allzu viel ist. Also war mein erster Ansatz Bitbanging. Die Daten sind mit steigender Flanke der Clock-Leitung gültig - also <strike>schreibe</strike> kopiere ich mir erst einmal ein Testprogramm in Python zusammen, das einen Interrupt aktiviert, die Frequenz misst und auf der Konsole ausgibt: <source lang="python"> #!/usr/bin/env python2.7 # original script by Alex Eames http://RasPi.tv import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) count = 0 def my_callback(channel): global count count += 1 GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback) try: while True: time.sleep(1) print "%i Hz" % count count = 0 except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit </source> Auf der anderen Seite hängt ein Logic 8, der zum Signalgenerator umfunktioniert wurde. Bis IIRC ca. 80 kHz funktioniert die Messung, danach gibt es aliasing. Gleichzeitig steigt die CPU-Last bei den höheren Frequenzen auf 67 %. Nicht wirklich was ich mir vorgestellt habe. In C habe ich es nicht ausprobiert, bin mir aber ziemlich sicher, dass dort die Schwuppdizität deutlich besser ist. ==Hardware-SPI== Streng genommen stellt der Raspberry nur einen Hardware-SPI-Master an seinem Pinheader zur Verfügung, allerdings lässt sich dessen PCM-Port als [http://offis.github.io/raspi-directhw/group__spisl.html SPI-Slave missbrauchen] (danke an Hans für den Hinweis). Der erste Satz auf der Projektseite macht allerdings nicht viel Mut: "[...] even though it has some serious limitations". Kurz: es gibt keinen Chip-Select, den muss man manuell implementieren. Müsste aufgrund der etwas [[Prozeda-Decoder#0x09|verschwurbelten Kommunikation]] sowieso gemacht werden. Chip sieht während der Kommunikation maximal 500 Hz, was ebenfalls problemlos möglich sein sollte. Auch wenn das alles verlockend klingt: Ich kneife. In Sachen C unter Linux bin ich überhaupt nicht fit - um es wirklich sauber zu implementieren wäre zudem sicher ein Kernel-Modul fällig. Damit wäre auch die eingangs gestellte Frage beantwortet: Nein, aktuell nicht. =Adapter= Allerdings gibt es Mikrocontroller-Software, die funktioniert. Fehlt nur noch eine zum Raspberry passende Hardware. ==Hardware== Mini-DIN-Buchse, Optokoppler, Mikrocontroller und Buchsenleiste reichten als Minimalbeschaltung für den Raspi. Ok, noch ein bisschen Außenbeschaltung, aber im Großen und Ganzen ist das alles. Die Stromversorgung erfolgt durch den Prozeda-Regler; durch den Optokoppler gibt es keine Wechselwirkung zwischen Regler und Pi (falls eine Seite nicht mit Strom versorgt wird). Mit dem Raspberry Pi Zero als Referenz sind die Bauteile so platziert, dass die Mini-DIN-Buchse als Verlängerung der langen Kante des Pi agiert: <gallery> pirozeda_sch.png | Schaltplan des Adapters pirozeda_brd.png | Layout des Adapters pirozeda_front.jpg | Aufgebaut und aufgesteckt pirozeda_size.jpg | weitere Perspektive </gallery> Die BOM ist dazu überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || FE07-2 || RND 205-00656 |- | 1 || SV2 || || MA03-2 || SL 2X40G 2,54 |- | 2 || C1, C5 || 100n || C0603 || X7R-G0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 2 || C3, C4 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q3 || 12M || MJ || 12,000000-MJ |- | 3 || R14, R15, R16 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C15 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R17 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C2 || 2u2 || C0805 || KEM X5R0805 2,2U |- | 1 || R13 || 470 || R0603 || RND 0603 1 470 |- | 1 || OK2 || 6N137 || DIL08 || 6N 137 |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 2 || U$2, U$3 || DUMMY || DUMMY || SE-DIO M08 |- | 1 || IC3 || MEGA88/168-AU || TQFP32-08 || ATMEGA 88PA-AU |- | 1 || X3 || MINIDIN8 || MINI-DIN8 || EB-DIOS M08 |- | 3 || C7, C11, C14 || na || C0603 || NPO-G0603 220P |} Im ersten Aufbau wurde ein ATmega88A verwendet, generell sollte auch die nicht-A-, P- oder PA-Variante sowie die verschiedenen Größen (8 bis 32 KB Flash) problemlos funktionieren. Für den ATmega48xx braucht's noch ein bisschen RAM-Optimierung. Was ich jedoch nicht bedacht habe: Für den Raspberry Pi 3 ist die Anordnung in mehrerlei Hinsicht schlecht: * die WLAN-Antenne wird vom Blechdeckel der Mini-DIN-Buchse verdeckt * die Leiterkarte passt so überhaupt nicht ins Gehäuse (kollidiert so mit der Wand, dass man ein großes Stück heraustrennen müsste) * Pads für den Optokoppler kollidieren mit dem (optionalen) Kühlkörper des Prozessors Aber hey, der Adapter funktioniert im ersten Anlauf. Um die oben genannten Nachteile zu umgehen habe ich die Buchsenleiste entfernt und durch eine Stiftleiste auf der anderen Seite der Leiterkarte ersetzt. So kann der Adapter mit einem Flachbandkabel mit dem Pi verbunden werden. Der Pinheader für ISP ist absichtlich so platziert, dass der Pfostenverbinder nicht versehentlich auf ihn gesteckt werden kann: <gallery> pirozeda_fixed_top.jpg | Umgebauter Adapter am Flachbandkabel </gallery> Ein weiterer - eher dümmlicher Layoutfehler - ist die Platzierung von C2. Ich habe die Leiterkarte zu oft im Kopf gedreht und das Bauteil ist genau auf der Kante der Mini-DIN-Buchse gelandet. Da die Kondensatoren der Tiefpässe nicht platziert sind, konnte er einfach zwischen Pin 5 der Buchse und Pin 2 von C14 eingelötet werden. Um Kurzschlüsse zu vermeiden hilft ein Stück Kapton-Tape an Stelle des C2. Als Verbindung zwischen Solarregler und Adapter dient ein Straight-Through-Kabel, das ich selbst zusammengelötet habe. Obwohl nicht alle Pins benötigt werden (Pin 4 (GND), 5 (3,3 V), 6 (MOSI), 7 (SCK) und 8 (!CS)), ist es eine sehr fummelige Angelegenheit - fertig konfektionierte Leitungen konnte ich nicht finden. Um zumindest nur einen Stecker löten zu müssen, kann die Seite in Richtung Adapter direkt auf die Leiterkarte gelötet werden. Für eine grundlegende Zugentlastung kann ein Kabelbinder durch die Befestigungslöcher geführt werden. Eine Leitungslänge von 2 m stellte in meinen Tests kein Problem dar, mit großer Wahrscheinlichkeit geht da auch ein gutes Stück mehr. Um das Löten der Leitung gänzlich zu vermeiden, merkte Frank (vom Original-Artikel) an, dass es wahrscheinlich geschickter wäre, den Adapter wie den Loggingstick aufzubauen, also die Leiterkarte direkt an den Mini-DIN-Stecker zu löten. Da zwangsläufig eine Leitung wegführt und der Schirm und die Plastikhülle drüber sollte (auch wenn er im Regler nicht angebunden ist), war mir das allerdings zu wackelig. Hans, der die erste Hardware bekommen hat, hat sich noch etwas mehr Arbeit gemacht und dem Ganzen das ModMyPi-Gehäuse (RPi 2/3 Case) mit Spacer und Abdeckung der USB-Ports und SD-Karte verpasst: <gallery> pirozeda_gehaeuse.jpg|Gehäuse von oben (Foto von Hans) pirozeda_gehaeuse2.jpg|Anschlussseite (Foto von Hans) pirozeda_gehaeuse3.jpg|Fertig installiert im Heizungskeller (Foto von Hans) </gallery> ==Firmware== {{Infobox AVR | Typ = ATmega88PA | Takt = 12 | FuseH = C5 | FuseL = DE | FuseE = 07 }} Die Originalfirmware kann nach Anpassung des Targets direkt verwendet werden, allerdings habe ich mich dafür entschieden, diese etwas zu anzupassen. Der AVR gibt die Pakete nun als Hex-String aus. Dadurch ist die Firmware gegenüber der Prozeda-Hardware so agnostisch wie möglich. Um Schluckauf zu vermeiden, werkelt der Watchdog mit relativ langem Timeout (2 Sekunden). Grund hierfür ist, dass er nur bei einer erfolgreich empfangenen Nachricht zurückgesetzt wird. Beim Flashen der Firmware muss unbedingt darauf geachtet werden, dass die Verbindung zum Solarregler getrennt wird, da sowohl SPI als auch ISP die gleichen Pins verwenden und es trotz der Serienwiderstände zu irreparablen Schäden kommen kann. Nach dem Verbinden mit dem Regler erfolgt beispielsweise folgende Ausgabe: <pre style="overflow: auto"> Built on: Oct 30 2017 16:14:56 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000000000000000000000000000000000004 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 Logdata:200071008a013000e300e200fc08fc08fc080600fc08fc08e60000000000b4ff0000000000000000000000000000000000000000000000000000000001000200000120e8 Display:20204b6f6c6c656b746f722020202020202020202020202020323220052d54203232203233200101180000000000000100000000000000000000000000000005 </pre> Die Konfiguration des UART ist 115200 Baud 8N1, Zeilenenden sind CR+LF (\r\n). Neben den oben gezeigten Ausgaben kann auch die Meldung "rxErr" gesendet werden, falls eine Nachricht nicht richtig erkannt wurde. Zusätzlich gibt die Firmware die ersten 200 Header-Zeilen nach dem Start des Mikrocontrollers aus, was die Erstellung der Konfiguration erleichtert. ==Download/Update der Firmware== Hier liegen mittlerweile 3 dedizierte AVR-Programmer herum. Was aber, wenn man nur den Raspberry hat? AVRDUDE hat mittlerweile Unterstützung für SPI-Module unter Linux. Eine ausführliche Anleitung findet sich auf [https://www.mikrocontroller.net/articles/Raspberry_Pi_als_Universalprogrammer mikrocontroller.net] Die Verbindung ist wie folgt herzustellen: {| class="wikitable" ! Signalname || Adapter SV2 Pin || Raspberry GPIO || Raspberry Pin || Farbe im Bild |- | MISO || 1 || BCM 9 || 21 || Grün |- | 3V3 || 2 || 3V3 || 17 || Rot |- | SCK || 3 || BCM 11 || 23 || Violett |- | MOSI || 4 || BCM 10 || 19 || Blau |- | !RES || 5 || BCM 25 || 22 || Weiß |- | GND || 6 || GND || 20 || Schwarz |} Zur Veranschaulichung noch ein Bild anhand eines Raspberry Pi Zero und einer Mockup-Leiterkarte: <gallery> pirozeda_flashing.jpg | Verbindungen zum Flashen des Mikrocontrollers </gallery> Richtig verbunden und mit (wichtig!) abgestecktem Regler lässt sich mit folgende Befehle der AVR fusen & flashen: <source lang="shell"> sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U lfuse:w:0xDE:m -U hfuse:w:0xC5:m -U efuse:w:0x07:m sudo /usr/local/bin/avrdude -c linuxspi -p m88p -P /dev/spidev0.0 -U flash:w:"ProzedaReader.hex" </source> AVRDUDE bietet keine explizite Unterstützung für den ATmega88PA. Das ist allerdings auch nicht nötig, da er bis auf kleine Unterschiede [http://ww1.microchip.com/downloads/en/AppNotes/doc8196.pdf funktional dem ATmega88P] entspricht. =[[Pirozeda-HAT]]= Um den Artikel übersichtlicher zu halten, gibt es einen gesonderten Arikel für den [[Pirozeda-HAT]] =Software auf dem Raspberry= ==Vorbereitung== Um den Adapter nutzen zu können, muss zunächst die Konsole auf dem UART deaktiviert werden. Das geht entweder über <code>sudo raspi-config</code> (keine Konsole aber UART aktiv) oder in der Datei <code>boot/cmdline.txt</code> - in ihr muss der Eintrag <code>console=serial0,115200</code> entfernt werden - die Änderung zieht erst nach einem Neustart. ===Vor Pirozeda 0.4=== Anschließend ein paar Module für Python - damit es einfach geht vorab (falls noch nicht vorhanden) - pip installieren: <source lang="shell"> sudo apt-get install python-pip sudo python -m pip install pyserial sudo python -m pip install python-jsonrpc </source> Nun kann mit miniterm getestet werden, ob was durchkommt: <source lang="shell"> sudo python -m serial.tools.miniterm /dev/serial0 115200 </source> Es sollten mehrere Nachrichten innerhalb einer Sekunde angezeigt werden. Ist man fertig, kann das Terminal (zumindest bei deutschem Tastatur-Layout) mit Strg+5 beendet werden. ===Ab Pirozeda 0.4=== Pirozeda ab 0.4 verwendet Python 3. Dementsprechend müssen die Module für die neuere Plattform installiert werden. Für JSON-RPC wird nun eine andere Lib verwendet, die zugleich "Werkzeug" als Webserver verwendet: <source lang="shell"> sudo python3 -m pip install json-rpc werkzeug pyserial </source> Auch hier kann über <code>miniterm</code> geprüft werden, ob Daten ankommen. ==Backend== Auch wenn die Daten vorverarbeitet vom Mikrocontroller kommen, lässt sich mit ihnen noch nicht allzu viel anfangen. Deshalb muss ein Programm her, das sie entgegennimmt, weiter verarbeitet und dem Nutzer zur Verfügung stellt. Zur Umsetzung dessen habe ich Python 2.7 verwendet. Das Programm liest die Daten über die Klasse <code>ProzedaReader</code> ein und stellt sie über verschiedene Events bzw. Puffer bereit. Über die Klassen <code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code> können die Daten (unter der Verwendung der zum eingesetzten Regler gehörenden Konfiguration) decodiert werden. <code>pirozeda.py</code> ist das Hauptprogramm und übernimmt das in den Settings konfigurierbare Logging und die Bereitstellung der Daten über die JSON-Schnittstelle. ===ProzedaReader=== Der Prozedareader liest über einen Thread die Daten von der seriellen Schnittstelle ein und wandelt diese in die entsprechenden Objekte (<code>ProzedaLogdata</code> und <code>ProzedaDisplaydata</code>) um und ruft folgende Callbacks auf: * <code>evt_rawdata_received(self, timestamp, line)</code> * <code>evt_logdata_received(self, entry)</code> * <code>evt_displaydata_received(self, entry)</code> * <code>evt_error_received(self, timestamp, errortype)</code> Ihnen können Methoden zugewiesen werden, die beim entsprechenden Ereignis aufgerufen werden. Aber Achtung: der Aufruf findet innerhalb des serialreader-Threads statt. Gleichzeitig werden standardmäßig die letzten 10 Log- und Displaydata-Nachrichten im Cache gehalten. Die Klasse <code>ProzedaLogdata</code> ist der Container für Logdaten, die sie beim instanziieren nur in das neue Objekt übernimmt. Das Parsen muss manuell durchgeführt werden, da es für das reine Logging nicht benötigt wird und sonst unnötig Ressourcen belegt werden würden. Wichtig und ziemlich unschön: bevor Daten geparst werden können, muss die Spaltenkonfiguration mit der statischen Methode <code>set_config</code> gesetzt werden. Das macht die Klasse undynamisch, allerdings ist die Wahrscheinlichkeit, dass man mehrere Systeme mit einer Anwendungsinstanz abdeckt eher gering. Als es mit der Zielhardware (Sungo SXL - ohne plus) in Betrieb genommen wurde fiel auf, dass sich die vom Regler gesendeten Datensätze zur Implementierung (Sungo SXLplus) unterscheiden. Das Gute ist, dass aufgrund der Agnostik des Adapters der Code bequem in Python angepasst werden kann. Dadurch dass die Daten roh geloggt werden (siehe unten) kann die Zuordnung des richtigen Parsers auch später nahezu ohne Informationsverlust erfolgen. Prinzipiell kann die Erkennung der Spaltenzuordnung auch komplett autonom erfolgen (die entsprechenden Daten können von der Hardware ausgegeben werden). Mir war der Nutzen dafür jedoch zu klein, da es sich dabei um eine einmalige Einrichtung handelt und die Zuordnung der Spalten bzw. deren Benamung und Anzeige-Einstellung je nach System unterschiedlich sein können. ===Pirozeda=== Das Pirozeda-Backend übernimmt das dateibasierte Logging und bietet eine JSON-RPC-Schnittstelle um z. B. aktuelle Daten abzurufen. Beim Logging habe ich mich bewusst gegen eine Datenbank entschieden, da die Implementierung ursprünglich als Demo und Einstiegspunkt für weitere Entwicklungen dienen sollte. In der aktuellen Konfiguration wird für jeden Tag eine Datei angelegt und alle 5-Minuten (einstellbar) ein Datensatz geschrieben. Das Dateiformat ist einfach gehalten. Der Dateiname entspricht dem Format "prozeda_YYYY-MM-DD.txt" und der Inhalt der Syntax Timestamp\tEntrytype\tEntrydata Aktuell werden drei Entrytypes verwendet - i (Info), d (Data) und w (Warning): <pre style="overflow: auto"> 1509546700.738 i Log opened 1509546760.524 d IABxAJcBDwDjAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINg= 1509546820.529 d IABxAJgBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINo= 1509546880.534 d IABxAJkBDwDkAOQA/Aj8CPwIBgD8CPwI6AAAAAAAtP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQACAAABINs= </pre> Ein scharfer Blick verrät: die Daten sind [[wpde:Base64|Base64]]-kodiert. Es geht effizienter, es geht schöner, aber wie bereits geschrieben: Einstiegspunkt. ===JSON-RPC=== Zur Schonung des Speichermediums wird nicht nach jedem Satz ein Flush (Schreiben ins Dateisystem) durchgeführt sondern dem Filewriter bzw. dem Betriebssystem überlassen. Um dennoch auf aktuelle Daten zugreifen zu können, werden die Datensätze der letzten 24 Stunden im Minutentakt (ebenfalls einstellbar) im RAM gehalten und stehen per JSON-RPC zur Verfügung. Darüber hinaus bietet das JSON-Interface bereits die wichtigsten Funktionen, um die erfassten Daten darstellen zu können. Diese sind in der Klasse <code>JsonrpcRequestHandler</code> beschrieben. {| class="wikitable" ! Befehl || Beschreibung |- | <code>info</code> || Ausgabe der Version des Backends |- | <code>settings_get</code> || Einstellungen des Backends (siehe pirozeda_settings.py) |- | <code>system_stats</code> || System-Statistik, darunter Speicherbelegung, Info über den Zustand des Readers und des Tracings |- | <code>current_logentry</code> || Gibt den aktuellen Logentry zurück |- | <code>columnheader_get</code> || Gibt die Kopfzeilen der vom Regler kommenden Daten zurück |- | <code>ramlog_getlast</code> || Gibt die letzten Einträge aus dem RAM-Log zurück |- | <code>fslog_flush</code> || Leert den Schreibpuffer für das Dateisystem-Log. Damit werden alle erfasten Daten auf die "Platte" geschrieben |- | <code>fslog_read</code> || Daten aus den Dateisystem-Logs lesen. Vor dem Lesen wird ein Flush durchgeführt, um wirklich alle Daten zu bekommen |- | <code>display_getcurrent</code> || Gibt die aktuellen Displaydaten zurück |- | <code>trace_start</code> || Startet das Backend-Trace für die vorgegebene Zeit. |- | <code>trace_stop</code> || Stoppt das Backend-Trace sofort (anstatt auf das Ablaufen des Timers zu warten) |- | <code>trace_live</code> || Gibt Livedaten der UART-Schnittstelle aus |} ==Frontend== Die Daten werden geloggt und bereitgestellt, aber noch nicht benutzerfreundlich dargestellt. Das muss das Frontend übernehmen: ===Webserver=== Als Webserver dient lighttpd mit PHP. PHP? Ja, PHP ("aber PHP!!11!eins" höre ich jetzt manche schreien - ja, ich weiß, das macht's nicht unbedingt besser). Natürlich kann auch Python - entweder direkt (nicht empfohlen) oder als weitere Instanz - als Webserver bzw. Sprache zum Abrufen der Daten verwendet werden. Die Grundidee zur Trennung von Backend und Server ist, die Angriffspunkte von außen zu verringern. Zur Einrichtung des Servers muss in der Shell folgendes eingegeben werden: <source lang="shell"> sudo apt-get install lighttpd sudo groupadd www-data sudo chown -R www-data:www-data /var/www/html sudo chmod -R 775 /var/www/html sudo usermod -G www-data -a pi sudo apt-get install php-common php-cgi php sudo lighty-enable-mod fastcgi-php </source> Aus nicht ganz erfindlichen Gründen hat lighttpd <code>index.htm</code> nicht in der Suche für Index-Seiten, also kann/sollte die Konfiguration angepasst werden: <source lang="shell"> sudo nano /etc/lighttpd/lighttpd.conf </source> ...und die Zeile beginnend mit <code>index-file.names</code> durch folgende ersetzt (oder angepasst) werden: <pre> index-file.names = ( "index.php", "index.htm", "index.html" ) </pre> Damit die Konfiguration gezogen wird, muss der Server neu gestartet werden: <source lang="shell"> sudo service lighttpd force-reload </source> ===Anwendung=== Eigentlich allenfalls als kleine Demo beabsichtigt, ist aus der Anwendung mehr geworden als ursprünglich gedacht. Bilder sagen hier mehr als Worte - angemerkt sei, dass mangels Regler vorab aufgezeichnete und schneller wiedergegebene Logdaten verwendet wurden, weswegen ein die Diagramme etwas gedrängt aussehen und die Displaydaten nicht angezeigt werden (wurden nicht aufgezeichnet). <gallery> pirozeda_currdata_plot.png | Aktuelle Daten als Plot pirozeda_histdata_plot.png | Historische Daten als Plot pirozeda_currdata_display.png | Displayanzeige und aktuelle Daten pirozeda_debug.png | Statistik und Debug-Optionen </gallery> Zum Plotten dient [https://plot.ly/javascript/ plotly.js], die Symbole im Display stammen von [https://fontawesome.com Font Awesome]. Das HTML-Dokument dient lediglich als Grundgerüst, die meisten Elemente werden per Javascript angelegt. Dreh- und Angelpunkt hierfür ist <code>pirozeda.js</code>. Um Standardaufgaben im DOM zu verkürzen, kommt <code>d.js</code> zum Einsatz. Durch die starke Verschachtelbarkeit der Befehle leidet allerdings die Lesbarkeit - das nur als Warnung. Nach dem Laden der Seite wird ein <code>SolarManager</code>-Objekt angelegt, dieses fragt zunächst die Einstellungen des Systems ab, bevor die restlichen Elemente generiert werden. Die Kommunikation mit dem Backend erfolgt über mehrere PHP-Dateien, die mehr oder weniger als Proxy agieren. Schließlich läuft das Backend (nicht ganz schön und sicher vermeidbar) als root und könnte somit größeres Unheil anrichten. Zwar könnte von der Seite auch direkt auf den JSON-RPC zugegriffen werden, was allerdings das Öffnen eines weiteren Ports (wenn man es nach draußen überhaupt freigeben will) erfordert. Gleichzeitig muss der Port auch von der Gegenseite erreichbar sein. In öffentlichen WLANs sind oft nur die Standardports zugelassen, um unbekannte Dienste zu sperren. Sobald die Einstellungen geladen sind, wird die Seite initialisiert, heißt: Erstellen der Elemente und befüllen der Daten (nachdem diese geladen wurden). Für den Plot werden die aktuellen und historischen Daten parallel verwaltet. Damit können die aktuellen im Hintergrund weiter aktualisiert bzw. erweitert werden, während historische Datensätze angezeigt werden. Der zweite Tab beinhaltet den aktuelle Displayinhalt und die aktuellen Messwerte vom Regler. Dies läuft über zwei parallele Requests, wobei Displaydaten nur übertragen werden, wenn auch tatsächlich der Tab angezeigt werden. Die Symbole stimmen zum Display sinngemäß überein, wobei Blinken noch nicht richtig dargestellt wird. Zwar ist die Latenz im Heimnetz gering genug, um den Displayinhalt quasi live zu übertragen, allerdings halte ich das für deutlich übertrieben. Besser und interessanter wäre hier, das Verhalten der Symbole im Backend zu analysieren, ein Blinken (und dessen Frequenz) zu erkennen und dies als Metainformation zu übertragen. Beim Displaytext habe ich noch nicht herausgefunden, was da tatsächlich übertragen wird. Es scheint zumindest keine 1:1-Kopie der Anzeige am Regler zu sein. Für Hinweise bin ich dankbar. Im Debug-Tab findet sich etwas Statistik und die Möglichkeit, Backend-Traces zu erstellen. Diese können durch einen erneuten Klick auf "Start" auf die ausgewählte Zeit verlängert werden. Die Aufzeichnung läuft im Hintergrund - also auch wenn die Seite geschlossen wurde - weiter. Mit einem Klick auf "Stopp" kann die Aufzeichnung vorzeitig beendet werden. Mit der Option "Rohdaten anzeigen" können im Tab "Aktuelle Daten" die Rohfassung der beiden Datentypen im Hex-Viewer angezeigt werden. Aktuell noch nicht implementiert aber geplant ist die Anzeige einer Heatmap z. B. über die Kollektortemperatur. Für den ersten Prototyp habe ich ältere Daten von der Solaranlage meiner Eltern verwendet. Die weißen Linien stellen Sonnenauf- und Untergang sowie den Zenit dar: <gallery> pirozeda_heatmap.png </gallery> Wie und bis wann die Integration erfolgt, kann ich noch nicht sagen. Wenn man Protokolle genauer verstehen will, hilft es häufig, den aktuellen Datenverkehr sehen und kommentieren zu können. Für diesen Zweck gibt es die Datei <code>trace.htm</code>: <gallery> pirozeda_livetrace.png </gallery> It's (a little) bigger on the inside. Lässt man das Kommentarfeld bei einem Druck auf Enter leer, wird ein Marker gesetzt. Über die Cursortasten können ferner die letzten Kommentare abgerufen werden. Über den Save-Button können die empfangenen Traces als HTML-Fragment exportiert werden. Anzumerken ist, dass die vom Server kommenden Zeilen den Timestamp vom Server verwenden, Kommentare jedoch die lokale Systemzeit. Für die Synchronisation wird im zurückgesendeten Datenpaket die aktuelle Serverzeit hinzugefügt aber momentan noch nicht verwendet. Marker und Kommentare werden aber an der richtigen Stelle in die Logs eingefügt, somit sollte ein Sprung in der Zeit zwischen Daten und Kommentaren kein wirkliches Problem darstellen. ==Konfiguration== Für die Konfiguration müssen im Normalfall nur zwei Dateien angepasst werden: ===prozeda_systems.py=== In dieser Datei werden die verschiedenen Systemkonfigurationen der Anlage abgelegt, die in der Datei <code>pirozeda_settings.py</code> zugewiesen und für das Aufschlüsseln der Datensätze verwendet wird. Dabei handelt es sich um ein Dictionary über die verschiedenen Anlagentypen, deren Schlüssel (Name der Konfiguration) eine Liste der Spalten zugewiesen ist. Hier ein Auszug der Konfiguration: <source lang="python"> prozeda_systems = { 'SungoSXL_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Zeit'], [0x01, 't0', 'T1 Kollektor'], [0x01, 't1', 'T2 Speicher 1- unten'], [0x01, 't2', 'T3 Speicher oben'], #... ], 'SungoSXLplus_1221_de' : [ [0x08, 'd', 'Datum'], [0x09, 'm', 'Uhrzeit'], [0x10, 's', 'Sekunden'], # ... ], #... } </source> Die Spalten enthalten folgende Elemente: * Spaltentyp (siehe Tabelle unten) - Int * Spaltenkürzel - String * Spaltenname - String * Optional(Standard: False): Spalte ausgeblendet - Boolean * Optional(Standard: None): Spaltenparameter - Any Folgende Spaltentypen werden unterstützt: {| class="wikitable" ! Wert || Länge im Datensatz || Beschreibung || Einheit |- | 0x00 || 2 || Dummy || |- | 0x01 || 2 || Temperature || °C |- | 0x02 || 2 || Radiation || W |- | 0x07 || 2 || Storage || kWh |- | 0x08 || 2 || Date || |- | 0x09 || 2 || Time || min |- | 0x0A || 1 || Output || |- | 0x0B || 2 || Function active (Controller) || |- | 0x0C || 2 || Function active (status automatic/manual) || |- | 0x0D || 2 || Error Temperature || |- | 0x0E || 2 || Error Output || |- | 0x0F || 2 || Storage || h |- | 0x10 || 2 || Seconds || |- | 0x13 || 2 || Flowrate || l/min |- | 0x1B || 2? || Tapping || l/min/10 |- | 0xFE || - || used for local timestamp || |- | 0xFF || - || Unknown entry, length given in arg || |} ===pirozeda_settings.py=== Diese Datei beinhaltet die Konfiguration für den Betrieb des Backends. Am wichtigsten aus Nutzersicht ist die Einstellung des Systems und die Angabe der Logintervalle sowie Orte für die Dateiablage. Letztere muss zwangsläufig mit absoluten Pfaden erfolgen, da der Aufruf durch Cron in aller Regel in einem anderen Arbeitsverzeichnis erfolgt. Location entspricht der geographischen Lage der Anlage und wird momentan noch nicht verwendet. Mit ihr kann Sonnenauf- und Untergang sowie der Zenit berechnet werden, auch für die Abfrage von Wetterprognosen ist der Ort der Anlage wichtig. <source lang="python"> settings = { 'serialport' : { 'port': '/dev/serial0', 'baudrate' : 115200, }, 'system' : prozeda_systems['SungoSXL_1221_de'], 'server_address' : ('', 19000), 'fslog' : { # interval in seconds for the log entries to be written to the filesystem 'interval' : 5 * 60, # if started via cron, an absolute path is needed! 'dir' : '/home/pi/pirozeda/logs/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'ramlog' : { # interval in seconds for the log held in RAM 'interval' : 1 * 60, # see below 'length' : 0, }, 'trace' : { 'dir' : '/home/pi/pirozeda/traces/', 'prefix' : 'prozeda_', 'suffix' : '.txt', }, 'location' : { 'lon' : 48.3, # North 'lat' : 10.1, # East } } #... </source> ==Installation== Die Installation ist ziemlich einfach: Das Zip-Package unter Downloads herunterladen und den Ordner "<code>pirozeda</code>" z.B. in das Userverzeichnis des Benutzers <code>pi</code> verschieben. Sollte der Pfad anders gewählt werden, muss dieser, wie oben beschrieben, angepasst werden. Hier sollte auch die Systemkonfiguration ausgewählt werden. Ein paar sind bereits in <code>prozeda_systems.py</code> vordefiniert. Der Inhalt des Ordners webserver muss nach <code>/var/www/html/</code>. ===Vor Pirozeda 0.4=== Anschließend kann bzw. sollte die Ausführung des Backends als Cronjob aktiviert werden, dazu <source lang="shell"> crontab -e </source> ausführen und folgende Zeile hinzufügen: <pre> @reboot python /home/pi/pirozeda/pirozeda.py </pre> Nach einem Neustart des Pi sollten die Daten automatisch gesammelt und zur Verfügung gestellt werden. ===Ab Pirozeda 0.4=== Ab Pirozeda 0.4 kann das Script als [http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/ Service] ausgeführt werden. Das entsprechende Script ist für die Verwendung in <code>/home/pi/pirozeda</code> vorbereitet und kann einfach wie folgt installiert werden: <source lang="shell"> sudo chmod +x pirozeda.py sudo cp pirozeda.sh /etc/init.d sudo chmod +x /etc/init.d/pirozeda.sh sudo update-rc.d pirozeda.sh defaults sudo /etc/init.d/pirozeda.sh start </source> Wer Pirozeda woanders installieren möchte, kann das Shellscript jederzeit entsprechend anpassen. Auch die Verwendung von cron ist natürlich weiterhin möglich, allerdings muss nun python3 verwendet werden. Update 21.04.2019: <code>pirozeda.py</code> muss für die Verwendung der Shell-Datei ebenfalls als ausführbar markiert sein. ==Sicherheit== IoT und Sicherheit findet man oft im Kontext Probleme, Lücken und Missbrauch. Ganz ehrlich: hier wurde nicht auf Sicherheit geachtet. Allgemein halte ich es für sinnvoller, den Reader nur im Intranet, also ohne Erreichbarkeit von außen, einzurichten. Erste Schritte zu mehr Sicherheit wären: * Das Backend nicht mehr als Root laufen lassen * Striktere Parameterprüfung in den PHP-Scripts oder selbige durch etwas besseres ersetzen * Benutzerauthentifikation für den Webserver aktivieren * SSL-Zertifikat installieren * ... =Anmerkungen= * Vielen Dank an Hans für die Leihgabe der Prozeda-Hardware gegen die ich testen und neue Erkenntnisse gewinnen konnte * Für einfacher Firmware-Updates sollte zusätzlich die Rx-Leitung des AVR verbindbar und ein entsprechender Bootloader vorhanden sein. Am besten wäre wohl ein ADUM1301 (o. ä.) mit dem ein Update ohne physischen Zugriff auf die Hardware möglich wäre. * Dem Adapter würde eine Status-LED nicht schaden * Wenn <code>pirozeda.py</code> crasht, wird sie nicht neu gestartet. Ein Shellscript, das die Ausführung in eine Schleife nimmt, sollte ausreichen. =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Git= Das Projekt liegt auch bei GitHub: https://github.com/chris-heo/pirozeda =Download= ==Vor Pirozeda 0.4== [[Datei:Pirozeda.zip]] enthält: * Designdaten im EAGLE-Format * Firmware (Atmel Studio-Projekt und vorkompiliert) für den ATmega88PA * Python-Backend * Webfrontend ==Ab Pirozeda 0.4== [[Datei:Pirozeda rpi.zip]] enthält: * Python-Backend * Webfrontend ==Änderungen== === 2017-11-??: Version 0.1 === * Erstes (nicht-öffentliches) PoC === 2018-04-15: Version 0.2 === * Erster öffentlicher Release === 2018-08-05: Version 0.3 === * Falsche Anzeige von Speicher <nowiki>[kWh]</nowiki> Speicher <nowiki>[h]</nowiki>, Volumenstrom <nowiki>[l/min]</nowiki> korrigiert * Timingproblem mit Displaydata-Nachrichten mit bestimmten Reglern korrigiert * Ausgabe von Konsolen-Nachrichten vom pyjsonrpc-Webserver deaktiviert * "no data received" wird nun mit einem Zeitstempel ausgegeben * Zwei (etwas zusammengehackte) Scripts zum Dekodieren von (Backend-)Logs hinzugefügt * Firmware sendet nun 200 Header-Nachrichten nach dem Einschalten des Decoders. Aktuell findet keine Auswertung statt - dies ist im Backend noch nicht implementiert. Diese Nachrichten dienen der einfacheren Erstellung von Konfigurationen und zur Diagnose * 3D-Diagramm für historische Daten hinzugefügt. Achtung: Das vollständige plotly.js ist nun eingebunden. Es ist verdammt groß und daher für mobile Endgeräte eher weniger geeignet. Ferner scheint Firefox Quantum nach Zerstörung des WebGL-Kontexts den GPU-Speicher nicht wieder freizugeben. (Chrome funktioniert besser) * Datumswerte für historische Daten werden nun vorbelegt * Displayanzeige entspricht nun der am Regler (dreizeilig) und ein paar Zeichen mehr werden richtig übersetzt * Zeitdrift beim Logging verringert <gallery> Pirozeda 3dplot.png | 3D-Diagramm (Vielen Dank an Hans für die Demo-Daten!) </gallery> === 2018-08-27: Version 0.31 === * Fehler korrigiert, weswegen aktuelle + Displaydaten sowie Statistik nicht aktualisiert werden. Das ist aufgrund des eingefügten 3D-Diagramms, was beim Laden/Aktualisieren der Daten (kontextsensitiv) nicht berücksichtigt wurde. (Notiz an mich: Tabs in Zukunft nicht per Index sondern Referenz abfragen) === 2019-03-30: Version 0.4 === * Umstellung Auf Python 3 * Script kann nun als Service verwendet werden * Fehlerkorrektur Anzeige von Volumenstrom * Mehr Informationen von der Firmware (Version/Build/Reglerversion/...) Ich habe leider keine Vergleichsdaten aber mir scheint die CPU-Last auf dem Pi bei aktivem Frontend sehr hoch, kann das jemand bestätigen? [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Raspberry Pi]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] 641f0cc9fbd57ac1ad8f76dd8e62ce634e1fb78b Testseite 0 2 1623 1208 2021-02-23T21:40:31Z Chris 2 wikitext text/x-wiki <WPPtags tags="MCP2221" /> {{Infobox AVR | Typ = AtMega Schießmichtot | Takt = 42 | FuseH = 0xFF | FuseL = 0xFF }} :<math>\int_{0}^{42} \frac{23}{42}x^{2} dx</math> <math>\int_{0}^{42} \frac{23}{42}x^{2} dx</math> Testseite, für interne Verwendung. <source lang="php"> <?php ladida(); $var = fopen("foobar"); ?> </source> <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> [[Kategorie:Elektronik]] cfc5312511538f145ea403130d58a4eb80c5529f Datei:Vbuspi 1.2b assy sch.png 6 709 1624 2021-02-26T20:27:37Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.3.zip 6 710 1625 2021-02-26T20:27:44Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.3 assy brd.png 6 711 1626 2021-02-26T20:27:58Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.3 assy direct sch.png 6 712 1627 2021-02-26T20:28:03Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.3 assy opto sch.png 6 713 1628 2021-02-26T20:28:10Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.3 assy sch.png 6 714 1629 2021-02-26T20:28:18Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder/Adapter für den Raspberry Pi v1.3 0 715 1631 2021-02-26T20:30:40Z Chris 2 Seite erstellt wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Who's perfect? Beim [[VBus-Decoder/Adapter_für_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] (und auch dem [[VBus-Decoder/Adapter_Nano|Nano]]) gibt es ein paar Unzulänglichkeiten, die jeweils ein Makeover der Leiterkarte erfordern. Da die Beliebtheit des Raspberry Pis deutlich größer als ein Arghduino für solche Anwendungen ist, gibt es hierfür zuerst (oder überhaupt) eine neue Version. Konkret handelt es sich um folgende Probleme, die mit der neuen Version behoben werden sollen: * Keine gestapelten Bauteile mehr * Hinreichend Eingangskapazität für mehr Zuverlässigkeit * Größere Bauteile zur einfacheren Bestückung * Rückkanal, um den Regler aktiv abfragen und parametrieren zu können =Änderungen= Aus dem MLCC-Kondensator wurde ein Elektrolyt, aktuell 100 µF, lässt sich bei Bedarf aber noch ein bisschen vergrößern. Dieser wird nun über einen Widerstand am Gleichrichter angebunden um den Ladestrom (und dadurch die Spannungseinbrüche auf dem Bus) zu verkleinern. Ob die Kombination aus 470 Ohm und 100 Mikrofarad gut ist, muss sich noch zeigen. Beim Spannungsregler ist der 3,3 V-Typ gekommen um zu bleiben. Dieser bietet neben dem etwas niedrigeren Preis den Vorteil, dass er auf der Eingangsseite einen größeren "Headroom" hat. Als Bestückoption gibt es nun auch einen Jumper, mit dem die Versorgung des Komparators ausgewählt werden kann - sollten die Referenzspannungen nach dem 3,3 V-Regler doch zu knapp werden, kann die Eingangsspannung des LDO verwendet werden. Offen ist natürlich, ob der zu erwartende Ripple in die Suppe spuckt. Die diskreten Bauteile sind nun alle im 0805-Package, dadurch wurden weite Teile des Layouts umgeworfen. Wer möchte, kann natürlich auch welche im 0603-Package (oder mit ein bisschen Wollen sollte auch 1206 gehen) auf die Footprints packen. Gänzlich neu ist der Rückkanal, die Dimensionierung dessen Bauteile erfolgte mit dem feuchten Finger in den Wind gehalten. Es ist eigentlich nichts besonderes zu erwarten, bei Bedarf kann allerdings einfach mit den Bauteilen gespielt werden. Die Änderungen kommen allerdings mit ein paar Kompromissen: * Die Leiterkarte wurde ein bisschen größer * Die Power-LED für den VBus ist rausgefallen (kein Platz, unnötiger Verbraucher) * Bei der Nutzung des Rückkanals ist... ** die Leiterkarte auf dem Pi Zero nur mit "Überhang" verwendbar ** keine galvanische Trennung möglich <gallery> Vbuspi_1.3_assy_sch.png | Schaltplan Vbuspi_1.3_assy_brd.png | Layout </gallery> =BOM= <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 470 || R0805 || RND 0805 1 470 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0805 || RND 0805 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_opto_sch.png | Bestückungsplan für optoisolierte Variante </gallery> </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X3 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 470 || R0805 || RND 0805 1 470 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 3 || Q1, Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_direct_sch.png | Bestückungsplan für unisolierte Variante </gallery> </tab> </tabs> =Downloads= * [[Datei:Vbuspi_1.3.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 1423bc73ade377d24c985da5bc92e78d11c8042c 1637 1631 2021-02-26T20:54:05Z Chris 2 /* Änderungen */ Hinweis zur Bauteilberechnung hinzugefügt wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Who's perfect? Beim [[VBus-Decoder/Adapter_für_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] (und auch dem [[VBus-Decoder/Adapter_Nano|Nano]]) gibt es ein paar Unzulänglichkeiten, die jeweils ein Makeover der Leiterkarte erfordern. Da die Beliebtheit des Raspberry Pis deutlich größer als ein Arghduino für solche Anwendungen ist, gibt es hierfür zuerst (oder überhaupt) eine neue Version. Konkret handelt es sich um folgende Probleme, die mit der neuen Version behoben werden sollen: * Keine gestapelten Bauteile mehr * Hinreichend Eingangskapazität für mehr Zuverlässigkeit * Größere Bauteile zur einfacheren Bestückung * Rückkanal, um den Regler aktiv abfragen und parametrieren zu können =Änderungen= Aus dem MLCC-Kondensator wurde ein Elektrolyt, aktuell 100 µF, lässt sich bei Bedarf aber noch ein bisschen vergrößern. Dieser wird nun über einen Widerstand am Gleichrichter angebunden um den Ladestrom (und dadurch die Spannungseinbrüche auf dem Bus) zu verkleinern. Ob die Kombination aus 470 Ohm und 100 Mikrofarad gut ist, muss sich noch zeigen. Beim Spannungsregler ist der 3,3 V-Typ gekommen um zu bleiben. Dieser bietet neben dem etwas niedrigeren Preis den Vorteil, dass er auf der Eingangsseite einen größeren "Headroom" hat. Die Neudimensionierung der Spannungsteiler basiert auf den Berechnungen von [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]]. Als Bestückoption gibt es nun auch einen Jumper, mit dem die Versorgung des Komparators ausgewählt werden kann - sollten die Referenzspannungen nach dem 3,3 V-Regler doch zu knapp werden, kann die Eingangsspannung des LDO verwendet werden. Offen ist natürlich, ob der zu erwartende Ripple in die Suppe spuckt. Die diskreten Bauteile sind nun alle im 0805-Package, dadurch wurden weite Teile des Layouts umgeworfen. Wer möchte, kann natürlich auch welche im 0603-Package (oder mit ein bisschen Wollen sollte auch 1206 gehen) auf die Footprints packen. Gänzlich neu ist der Rückkanal, die Dimensionierung dessen Bauteile erfolgte mit dem feuchten Finger in den Wind gehalten. Es ist eigentlich nichts besonderes zu erwarten, bei Bedarf kann allerdings einfach mit den Bauteilen gespielt werden. Die Änderungen kommen allerdings mit ein paar Kompromissen: * Die Leiterkarte wurde ein bisschen größer * Die Power-LED für den VBus ist rausgefallen (kein Platz, unnötiger Verbraucher) * Bei der Nutzung des Rückkanals ist... ** die Leiterkarte auf dem Pi Zero nur mit "Überhang" verwendbar ** keine galvanische Trennung möglich <gallery> Vbuspi_1.3_assy_sch.png | Schaltplan Vbuspi_1.3_assy_brd.png | Layout </gallery> =BOM= <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 470 || R0805 || RND 0805 1 470 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0805 || RND 0805 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_opto_sch.png | Bestückungsplan für optoisolierte Variante </gallery> </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X3 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 470 || R0805 || RND 0805 1 470 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 3 || Q1, Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_direct_sch.png | Bestückungsplan für unisolierte Variante </gallery> </tab> </tabs> =Downloads= * [[Datei:Vbuspi_1.3.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] c594a4fc6e07e169341c44f9769978374b22e1db VBus-Decoder/Adapter für den Raspberry Pi 0 706 1640 1632 2021-03-19T17:12:00Z Chris 2 /* Die Enttäuschung - Teil 2 */ BOM korrigiert wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Leiterkarten= Es gibt noch Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =Kostenreduzierte Variante/v1.2= Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ==Die Enttäuschung== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers]], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ==Die (vermeintliche) Lösung== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} ==Die Enttäuschung - Teil 2== Stefan schickte eine Mail mit einen sehr guten Verbesserungsvorschlag bzw. vielmehr Hinweis auf Fehler: <pre> Ich würde an deiner Stelle bei der 3,3V Schaltung den Spannungsteiler R8/R5 anpassen. An dessen Eingang können ~7V anliegen womit der OP dann 3,5V an seinem Eingang hat. Das ist bei 3,3V Versorgungsspannung etwas über der Spezifikation des verwendeten OPs. </pre> Das ist absolut richtig, die Spannung ist außerhalb der Spec. Der Fehler hat sich mit an Sicherheit grenzender Wahrscheinlichkeit eingeschlichen, weil beim Neudimensionieren der Schaltung nur die Teile berücksichtigt wurden, die direkt an +3V3 hängen. Schaut man noch etwas genauer ins Datenblatt entdeckt man, dass die Eingänge des LM393 für eine korrekte Funktion einen gewissen Abstand zu V+ haben müssen. Bei der Variante von TI sind das VDD - 1,5 V. Ok, das ist natürlich Mist. Aber beherrschbarer. Im Prinzip müssen nur die Widerstände für die Spannungsteiler neu berechnet werden. Jetzt kann man es sich natürlich einfach machen und die naheliegendsten Werte aus der E24-Reihe nehmen. Selbst für gut ausgestattete Widerstandslager zu Hause würde das eine Bestellung bei den üblichen Verdächtigen bedeuten. Dann hat man meistens noch die vermutlich selten genutzten Wert-Überreste in einer Schublade liegen und das Bestücken ist fehleranfälliger. Uncool. Also warum nicht so lange mit den Bauteilwerten jonglieren, bis es eine gute Kombination gibt? Kann man manuell machen, ist aber eher mühsam. Geht auch mit Excel, ist aber auch nicht das beste Tool dafür. Ob JavaScript so wirklich dafür geeignet ist, sei mal dahingestellt - dafür spricht allerdings, dass mittlerweile fast jedes Endgerät mit Farbdisplay eine passende Laufzeitumgebung installiert hat. Herausgekommen ist dieser [//hobbyelektronik.org/tools/komparator/ schlichte Rechner]. Zahlen eingeben und los geht's: {| class="wikitable" ! Bezeichnung || Wert || Kommentar |- | Versorgungsspannung Komparator || 3,3 V || |- | Maximale Eingangsspannung Komparator || 1,8 V || (3,3 - 1,5) V |- | Maximale Signalspannung || 6,8 V || (8,2 - 1,4) V |- | Obere Schwelle || 4,5 V || aus der VBus-Spec |- | Untere Schwelle || 4,0 V || aus der VBus-Spec |- |} Aktuell werden Widerstände aus der E6- und (damit es ein bisschen Mehr Auswahl gibt) E12-Reihe für die Bauteilsuche genutzt. Für die eingegebenen Werte ergibt sich eine schöne Kombination aus der E6-Reihe, die nur drei unterschiedliche Werte benötigt: {| class="wikitable" ! Referenz || Wert |- | R8 || 15 k |- | R5 || 4,7 k |- | R3 || 4,7 k |- | R4 || 2,2 k |- | R2 || 15 k |} Zur Gegenprobe - der Spannungsteiler gibt folgende Spannung aus: <math>(\textrm{8,2 V} - \textrm{1,4 V}) \cdot \frac{\textrm{4,7 k}}{\textrm{4,7 k} + \textrm{15 k}} = \textrm{6,8 V} \cdot \frac{\textrm{4,7}}{\textrm{19,7}} = \textrm{1,62 V}</math> Da ist noch gut Luft zu den Maximal 1,8 V - rechnet man rück, dürfte der Spannungsabfall über den Gleichrichter bis auf 0,65 (für beide Dioden) fallen, um auf eine Eingangsspannung von über 1,8 V am Komparator zu kommen Der Kondensator für den Tiefpass kann übrigens gleich bleiben. Die Grenzfrequenz steigt zwar ein wenig, der Wert ist jedoch weniger kritisch. Daraus ergibt sich folgender Schaltplan: <gallery> Vbuspi_1.2b_assy_sch.png|Schaltplan Version 1.2b </gallery> Die aktualisierte BOM lautet wie folgt: <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> Damit sollte nun der Komparator glücklich sein. Auch in der Simulation in LTspice passen die Schwellen und das Verhalten der Schaltung. Hierzu hatte Stefan folgende Anmerkung: <pre> Nicht gefallen tut mir der C6 von 100pF. Dadurch wird zwar die Referenz stabiler aber die Schwellenumschaltung beim Pegelwechsel wird langsamer. Damit reduziert sich die Störfestigkeit des Eingangssignals. Ich hätte es aber vermutlich auch so gemacht. </pre> Ja, das ist richtig - und auch ich war/bin über den Kondensator nicht so richtig glücklich. Das Bauteil ist meiner Meinung allerdings ein sehr einfacher und effektiver Weg, das beschriebene Problem - besonders im bereits existierenden Design - einfach zu umgehen. Da die Versorgung nicht 100 %ig stabil war, hatte er noch folgenden Ratschlag: <pre> Noch eine Anmerkung zu deiner Kostenreduktion mit dem TS5205 CX533. Ich vermute dass der Ausgangskondensator (C3) nicht passt (ESR zu hoch). LowDrop Regler sind bei zu hohem ESR instabil. Manchmal hilft ein 2ter Kondensator parallel zu C3 (so 10nF bis 100nF) um den Regler stabil zu bekommen. </pre> Was ich versucht habe aber nicht zum gewünschten Erfolg verhalf. Das Problem ist vermutlich eher, dass die Schaltung bei aktivem Optokoppler gänzlich aus den Bulk-Kondensatoren gespeist werden müssen. Da hilft nur mehr Kapazität am Eingang, weswegen als Workaround C5 "aufgedoppelt" werden sollte (Stapeln zweier Kondensatoren). Das ist zwar nicht so richtig schön, aber sollte in den meisten Fällen helfen. Aufgrund der verschiedenen Unzulänglichkeiten - und um den bei manchen Reglern erforderlichen Rückkanal zu haben - gibt es eine verbesserte Version der Hardware: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 9a5120e7b4267ddfac7efdf8bd8575272880ae5b 1642 1640 2021-03-29T11:02:08Z Chris 2 wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Leiterkarten= Sorry, aktuell gibt es keine mehr. =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =Kostenreduzierte Variante/v1.2= Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ==Die Enttäuschung== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers]], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ==Die (vermeintliche) Lösung== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} ==Die Enttäuschung - Teil 2== Stefan schickte eine Mail mit einen sehr guten Verbesserungsvorschlag bzw. vielmehr Hinweis auf Fehler: <pre> Ich würde an deiner Stelle bei der 3,3V Schaltung den Spannungsteiler R8/R5 anpassen. An dessen Eingang können ~7V anliegen womit der OP dann 3,5V an seinem Eingang hat. Das ist bei 3,3V Versorgungsspannung etwas über der Spezifikation des verwendeten OPs. </pre> Das ist absolut richtig, die Spannung ist außerhalb der Spec. Der Fehler hat sich mit an Sicherheit grenzender Wahrscheinlichkeit eingeschlichen, weil beim Neudimensionieren der Schaltung nur die Teile berücksichtigt wurden, die direkt an +3V3 hängen. Schaut man noch etwas genauer ins Datenblatt entdeckt man, dass die Eingänge des LM393 für eine korrekte Funktion einen gewissen Abstand zu V+ haben müssen. Bei der Variante von TI sind das VDD - 1,5 V. Ok, das ist natürlich Mist. Aber beherrschbarer. Im Prinzip müssen nur die Widerstände für die Spannungsteiler neu berechnet werden. Jetzt kann man es sich natürlich einfach machen und die naheliegendsten Werte aus der E24-Reihe nehmen. Selbst für gut ausgestattete Widerstandslager zu Hause würde das eine Bestellung bei den üblichen Verdächtigen bedeuten. Dann hat man meistens noch die vermutlich selten genutzten Wert-Überreste in einer Schublade liegen und das Bestücken ist fehleranfälliger. Uncool. Also warum nicht so lange mit den Bauteilwerten jonglieren, bis es eine gute Kombination gibt? Kann man manuell machen, ist aber eher mühsam. Geht auch mit Excel, ist aber auch nicht das beste Tool dafür. Ob JavaScript so wirklich dafür geeignet ist, sei mal dahingestellt - dafür spricht allerdings, dass mittlerweile fast jedes Endgerät mit Farbdisplay eine passende Laufzeitumgebung installiert hat. Herausgekommen ist dieser [//hobbyelektronik.org/tools/komparator/ schlichte Rechner]. Zahlen eingeben und los geht's: {| class="wikitable" ! Bezeichnung || Wert || Kommentar |- | Versorgungsspannung Komparator || 3,3 V || |- | Maximale Eingangsspannung Komparator || 1,8 V || (3,3 - 1,5) V |- | Maximale Signalspannung || 6,8 V || (8,2 - 1,4) V |- | Obere Schwelle || 4,5 V || aus der VBus-Spec |- | Untere Schwelle || 4,0 V || aus der VBus-Spec |- |} Aktuell werden Widerstände aus der E6- und (damit es ein bisschen Mehr Auswahl gibt) E12-Reihe für die Bauteilsuche genutzt. Für die eingegebenen Werte ergibt sich eine schöne Kombination aus der E6-Reihe, die nur drei unterschiedliche Werte benötigt: {| class="wikitable" ! Referenz || Wert |- | R8 || 15 k |- | R5 || 4,7 k |- | R3 || 4,7 k |- | R4 || 2,2 k |- | R2 || 15 k |} Zur Gegenprobe - der Spannungsteiler gibt folgende Spannung aus: <math>(\textrm{8,2 V} - \textrm{1,4 V}) \cdot \frac{\textrm{4,7 k}}{\textrm{4,7 k} + \textrm{15 k}} = \textrm{6,8 V} \cdot \frac{\textrm{4,7}}{\textrm{19,7}} = \textrm{1,62 V}</math> Da ist noch gut Luft zu den Maximal 1,8 V - rechnet man rück, dürfte der Spannungsabfall über den Gleichrichter bis auf 0,65 (für beide Dioden) fallen, um auf eine Eingangsspannung von über 1,8 V am Komparator zu kommen Der Kondensator für den Tiefpass kann übrigens gleich bleiben. Die Grenzfrequenz steigt zwar ein wenig, der Wert ist jedoch weniger kritisch. Daraus ergibt sich folgender Schaltplan: <gallery> Vbuspi_1.2b_assy_sch.png|Schaltplan Version 1.2b </gallery> Die aktualisierte BOM lautet wie folgt: <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> Damit sollte nun der Komparator glücklich sein. Auch in der Simulation in LTspice passen die Schwellen und das Verhalten der Schaltung. Hierzu hatte Stefan folgende Anmerkung: <pre> Nicht gefallen tut mir der C6 von 100pF. Dadurch wird zwar die Referenz stabiler aber die Schwellenumschaltung beim Pegelwechsel wird langsamer. Damit reduziert sich die Störfestigkeit des Eingangssignals. Ich hätte es aber vermutlich auch so gemacht. </pre> Ja, das ist richtig - und auch ich war/bin über den Kondensator nicht so richtig glücklich. Das Bauteil ist meiner Meinung allerdings ein sehr einfacher und effektiver Weg, das beschriebene Problem - besonders im bereits existierenden Design - einfach zu umgehen. Da die Versorgung nicht 100 %ig stabil war, hatte er noch folgenden Ratschlag: <pre> Noch eine Anmerkung zu deiner Kostenreduktion mit dem TS5205 CX533. Ich vermute dass der Ausgangskondensator (C3) nicht passt (ESR zu hoch). LowDrop Regler sind bei zu hohem ESR instabil. Manchmal hilft ein 2ter Kondensator parallel zu C3 (so 10nF bis 100nF) um den Regler stabil zu bekommen. </pre> Was ich versucht habe aber nicht zum gewünschten Erfolg verhalf. Das Problem ist vermutlich eher, dass die Schaltung bei aktivem Optokoppler gänzlich aus den Bulk-Kondensatoren gespeist werden müssen. Da hilft nur mehr Kapazität am Eingang, weswegen als Workaround C5 "aufgedoppelt" werden sollte (Stapeln zweier Kondensatoren). Das ist zwar nicht so richtig schön, aber sollte in den meisten Fällen helfen. Aufgrund der verschiedenen Unzulänglichkeiten - und um den bei manchen Reglern erforderlichen Rückkanal zu haben - gibt es eine verbesserte Version der Hardware: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 655f6c2421c22b61c6cf3a2e6ca920a28ff2dfaf 1643 1642 2021-03-30T15:28:02Z Chris 2 /* Die Enttäuschung - Teil 2 */ wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Leiterkarten= Sorry, aktuell gibt es keine mehr. =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =Kostenreduzierte Variante/v1.2= Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ==Die Enttäuschung== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers]], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ==Die (vermeintliche) Lösung== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} ==Die Enttäuschung - Teil 2== Stefan schickte eine Mail mit einen sehr guten Verbesserungsvorschlag bzw. vielmehr Hinweis auf Fehler: <pre> Ich würde an deiner Stelle bei der 3,3V Schaltung den Spannungsteiler R8/R5 anpassen. An dessen Eingang können ~7V anliegen womit der OP dann 3,5V an seinem Eingang hat. Das ist bei 3,3V Versorgungsspannung etwas über der Spezifikation des verwendeten OPs. </pre> Das ist absolut richtig, die Spannung ist außerhalb der Spec. Der Fehler hat sich mit an Sicherheit grenzender Wahrscheinlichkeit eingeschlichen, weil beim Neudimensionieren der Schaltung nur die Teile berücksichtigt wurden, die direkt an +3V3 hängen. Schaut man noch etwas genauer ins Datenblatt entdeckt man, dass die Eingänge des LM393 für eine korrekte Funktion einen gewissen Abstand zu V+ haben müssen. Bei der Variante von TI sind das VDD - 1,5 V. Ok, das ist natürlich Mist. Aber beherrschbarer. Im Prinzip müssen nur die Widerstände für die Spannungsteiler neu berechnet werden. Jetzt kann man es sich natürlich einfach machen und die naheliegendsten Werte aus der E24-Reihe nehmen. Selbst für gut ausgestattete Widerstandslager zu Hause würde das eine Bestellung bei den üblichen Verdächtigen bedeuten. Dann hat man meistens noch die vermutlich selten genutzten Wert-Überreste in einer Schublade liegen und das Bestücken ist fehleranfälliger. Uncool. Also warum nicht so lange mit den Bauteilwerten jonglieren, bis es eine gute Kombination gibt? Kann man manuell machen, ist aber eher mühsam. Geht auch mit Excel, ist aber auch nicht das beste Tool dafür. Ob JavaScript so wirklich dafür geeignet ist, sei mal dahingestellt - dafür spricht allerdings, dass mittlerweile fast jedes Endgerät mit Farbdisplay eine passende Laufzeitumgebung installiert hat. Herausgekommen ist dieser [//hobbyelektronik.org/tools/komparator/ schlichte Rechner]. Zahlen eingeben und los geht's: {| class="wikitable" ! Bezeichnung || Wert || Kommentar |- | Versorgungsspannung Komparator || 3,3 V || |- | Maximale Eingangsspannung Komparator || 1,8 V || (3,3 - 1,5) V |- | Maximale Signalspannung || 6,8 V || (8,2 - 1,4) V |- | Obere Schwelle || 4,5 V || aus der VBus-Spec |- | Untere Schwelle || 4,0 V || aus der VBus-Spec |- |} Aktuell werden Widerstände aus der E6- und (damit es ein bisschen Mehr Auswahl gibt) E12-Reihe für die Bauteilsuche genutzt. Für die eingegebenen Werte ergibt sich eine schöne Kombination aus der E6-Reihe, die nur drei unterschiedliche Werte benötigt: {| class="wikitable" ! Referenz || Wert |- | R8 || 15 k |- | R5 || 4,7 k |- | R3 || 4,7 k |- | R4 || 2,2 k |- | R2 || 15 k |} Zur Gegenprobe - der Spannungsteiler gibt folgende Spannung aus: <math>(\textrm{8,2 V} - \textrm{1,4 V}) \cdot \frac{\textrm{4,7 k}}{\textrm{4,7 k} + \textrm{15 k}} = \textrm{6,8 V} \cdot \frac{\textrm{4,7}}{\textrm{19,7}} = \textrm{1,62 V}</math> Da ist noch gut Luft zu den Maximal 1,8 V - rechnet man rück, dürfte der Spannungsabfall über den Gleichrichter bis auf 0,65 (für beide Dioden) fallen, um auf eine Eingangsspannung von über 1,8 V am Komparator zu kommen Der Kondensator für den Tiefpass kann übrigens gleich bleiben. Die Grenzfrequenz steigt zwar ein wenig, der Wert ist jedoch weniger kritisch. Daraus ergibt sich folgender Schaltplan: <gallery> Vbuspi_1.2b_assy_sch.png|Schaltplan Version 1.2b </gallery> Die aktualisierte BOM lautet wie folgt: <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2* || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2* || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> *) am besten zwei verwenden und stapeln, damit der Schaltung bei längeren Nachrichten die Puste nicht ausgeht - siehe unten Damit sollte nun der Komparator glücklich sein. Auch in der Simulation in LTspice passen die Schwellen und das Verhalten der Schaltung. Hierzu hatte Stefan folgende Anmerkung: <pre> Nicht gefallen tut mir der C6 von 100pF. Dadurch wird zwar die Referenz stabiler aber die Schwellenumschaltung beim Pegelwechsel wird langsamer. Damit reduziert sich die Störfestigkeit des Eingangssignals. Ich hätte es aber vermutlich auch so gemacht. </pre> Ja, das ist richtig - und auch ich war/bin über den Kondensator nicht so richtig glücklich. Das Bauteil ist meiner Meinung allerdings ein sehr einfacher und effektiver Weg, das beschriebene Problem - besonders im bereits existierenden Design - einfach zu umgehen. Da die Versorgung nicht 100 %ig stabil war, hatte er noch folgenden Ratschlag: <pre> Noch eine Anmerkung zu deiner Kostenreduktion mit dem TS5205 CX533. Ich vermute dass der Ausgangskondensator (C3) nicht passt (ESR zu hoch). LowDrop Regler sind bei zu hohem ESR instabil. Manchmal hilft ein 2ter Kondensator parallel zu C3 (so 10nF bis 100nF) um den Regler stabil zu bekommen. </pre> Was ich versucht habe aber nicht zum gewünschten Erfolg verhalf. Das Problem ist vermutlich eher, dass die Schaltung bei aktivem Optokoppler gänzlich aus den Bulk-Kondensatoren gespeist werden müssen. Da hilft nur mehr Kapazität am Eingang, weswegen als Workaround C5 "aufgedoppelt" werden sollte (Stapeln zweier Kondensatoren). Das ist zwar nicht so richtig schön, aber sollte in den meisten Fällen helfen. Aufgrund der verschiedenen Unzulänglichkeiten - und um den bei manchen Reglern erforderlichen Rückkanal zu haben - gibt es eine verbesserte Version der Hardware: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] d275b9321783ed44b02a6b7479b1182f62def303 1644 1643 2021-03-30T15:28:32Z Chris 2 /* Die Enttäuschung - Teil 2 */ wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Leiterkarten= Sorry, aktuell gibt es keine mehr. =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =Kostenreduzierte Variante/v1.2= Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ==Die Enttäuschung== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers]], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ==Die (vermeintliche) Lösung== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} ==Die Enttäuschung - Teil 2== Stefan schickte eine Mail mit einen sehr guten Verbesserungsvorschlag bzw. vielmehr Hinweis auf Fehler: <pre> Ich würde an deiner Stelle bei der 3,3V Schaltung den Spannungsteiler R8/R5 anpassen. An dessen Eingang können ~7V anliegen womit der OP dann 3,5V an seinem Eingang hat. Das ist bei 3,3V Versorgungsspannung etwas über der Spezifikation des verwendeten OPs. </pre> Das ist absolut richtig, die Spannung ist außerhalb der Spec. Der Fehler hat sich mit an Sicherheit grenzender Wahrscheinlichkeit eingeschlichen, weil beim Neudimensionieren der Schaltung nur die Teile berücksichtigt wurden, die direkt an +3V3 hängen. Schaut man noch etwas genauer ins Datenblatt entdeckt man, dass die Eingänge des LM393 für eine korrekte Funktion einen gewissen Abstand zu V+ haben müssen. Bei der Variante von TI sind das VDD - 1,5 V. Ok, das ist natürlich Mist. Aber beherrschbarer. Im Prinzip müssen nur die Widerstände für die Spannungsteiler neu berechnet werden. Jetzt kann man es sich natürlich einfach machen und die naheliegendsten Werte aus der E24-Reihe nehmen. Selbst für gut ausgestattete Widerstandslager zu Hause würde das eine Bestellung bei den üblichen Verdächtigen bedeuten. Dann hat man meistens noch die vermutlich selten genutzten Wert-Überreste in einer Schublade liegen und das Bestücken ist fehleranfälliger. Uncool. Also warum nicht so lange mit den Bauteilwerten jonglieren, bis es eine gute Kombination gibt? Kann man manuell machen, ist aber eher mühsam. Geht auch mit Excel, ist aber auch nicht das beste Tool dafür. Ob JavaScript so wirklich dafür geeignet ist, sei mal dahingestellt - dafür spricht allerdings, dass mittlerweile fast jedes Endgerät mit Farbdisplay eine passende Laufzeitumgebung installiert hat. Herausgekommen ist dieser [//hobbyelektronik.org/tools/komparator/ schlichte Rechner]. Zahlen eingeben und los geht's: {| class="wikitable" ! Bezeichnung || Wert || Kommentar |- | Versorgungsspannung Komparator || 3,3 V || |- | Maximale Eingangsspannung Komparator || 1,8 V || (3,3 - 1,5) V |- | Maximale Signalspannung || 6,8 V || (8,2 - 1,4) V |- | Obere Schwelle || 4,5 V || aus der VBus-Spec |- | Untere Schwelle || 4,0 V || aus der VBus-Spec |- |} Aktuell werden Widerstände aus der E6- und (damit es ein bisschen Mehr Auswahl gibt) E12-Reihe für die Bauteilsuche genutzt. Für die eingegebenen Werte ergibt sich eine schöne Kombination aus der E6-Reihe, die nur drei unterschiedliche Werte benötigt: {| class="wikitable" ! Referenz || Wert |- | R8 || 15 k |- | R5 || 4,7 k |- | R3 || 4,7 k |- | R4 || 2,2 k |- | R2 || 15 k |} Zur Gegenprobe - der Spannungsteiler gibt folgende Spannung aus: <math>(\textrm{8,2 V} - \textrm{1,4 V}) \cdot \frac{\textrm{4,7 k}}{\textrm{4,7 k} + \textrm{15 k}} = \textrm{6,8 V} \cdot \frac{\textrm{4,7}}{\textrm{19,7}} = \textrm{1,62 V}</math> Da ist noch gut Luft zu den Maximal 1,8 V - rechnet man rück, dürfte der Spannungsabfall über den Gleichrichter bis auf 0,65 (für beide Dioden) fallen, um auf eine Eingangsspannung von über 1,8 V am Komparator zu kommen Der Kondensator für den Tiefpass kann übrigens gleich bleiben. Die Grenzfrequenz steigt zwar ein wenig, der Wert ist jedoch weniger kritisch. Daraus ergibt sich folgender Schaltplan: <gallery> Vbuspi_1.2b_assy_sch.png|Schaltplan Version 1.2b </gallery> Die aktualisierte BOM lautet wie folgt: <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2* || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2* || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> <nowiki>*)</nowiki> am besten zwei verwenden und stapeln, damit der Schaltung bei längeren Nachrichten die Puste nicht ausgeht - siehe unten Damit sollte nun der Komparator glücklich sein. Auch in der Simulation in LTspice passen die Schwellen und das Verhalten der Schaltung. Hierzu hatte Stefan folgende Anmerkung: <pre> Nicht gefallen tut mir der C6 von 100pF. Dadurch wird zwar die Referenz stabiler aber die Schwellenumschaltung beim Pegelwechsel wird langsamer. Damit reduziert sich die Störfestigkeit des Eingangssignals. Ich hätte es aber vermutlich auch so gemacht. </pre> Ja, das ist richtig - und auch ich war/bin über den Kondensator nicht so richtig glücklich. Das Bauteil ist meiner Meinung allerdings ein sehr einfacher und effektiver Weg, das beschriebene Problem - besonders im bereits existierenden Design - einfach zu umgehen. Da die Versorgung nicht 100 %ig stabil war, hatte er noch folgenden Ratschlag: <pre> Noch eine Anmerkung zu deiner Kostenreduktion mit dem TS5205 CX533. Ich vermute dass der Ausgangskondensator (C3) nicht passt (ESR zu hoch). LowDrop Regler sind bei zu hohem ESR instabil. Manchmal hilft ein 2ter Kondensator parallel zu C3 (so 10nF bis 100nF) um den Regler stabil zu bekommen. </pre> Was ich versucht habe aber nicht zum gewünschten Erfolg verhalf. Das Problem ist vermutlich eher, dass die Schaltung bei aktivem Optokoppler gänzlich aus den Bulk-Kondensatoren gespeist werden müssen. Da hilft nur mehr Kapazität am Eingang, weswegen als Workaround C5 "aufgedoppelt" werden sollte (Stapeln zweier Kondensatoren). Das ist zwar nicht so richtig schön, aber sollte in den meisten Fällen helfen. Aufgrund der verschiedenen Unzulänglichkeiten - und um den bei manchen Reglern erforderlichen Rückkanal zu haben - gibt es eine verbesserte Version der Hardware: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 694cd58fada97232c4b27e716e8a2be2ef4eb85e 1649 1644 2021-06-08T19:57:18Z Chris 2 Hinweistext zur v1.3 fett wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' '''Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[#Die Enttäuschung - Teil 2|1.2b]] nachzubauen.''' =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Leiterkarten= Sorry, aktuell gibt es keine mehr. =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =Kostenreduzierte Variante/v1.2= Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ==Die Enttäuschung== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers]], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ==Die (vermeintliche) Lösung== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} ==Die Enttäuschung - Teil 2== Stefan schickte eine Mail mit einen sehr guten Verbesserungsvorschlag bzw. vielmehr Hinweis auf Fehler: <pre> Ich würde an deiner Stelle bei der 3,3V Schaltung den Spannungsteiler R8/R5 anpassen. An dessen Eingang können ~7V anliegen womit der OP dann 3,5V an seinem Eingang hat. Das ist bei 3,3V Versorgungsspannung etwas über der Spezifikation des verwendeten OPs. </pre> Das ist absolut richtig, die Spannung ist außerhalb der Spec. Der Fehler hat sich mit an Sicherheit grenzender Wahrscheinlichkeit eingeschlichen, weil beim Neudimensionieren der Schaltung nur die Teile berücksichtigt wurden, die direkt an +3V3 hängen. Schaut man noch etwas genauer ins Datenblatt entdeckt man, dass die Eingänge des LM393 für eine korrekte Funktion einen gewissen Abstand zu V+ haben müssen. Bei der Variante von TI sind das VDD - 1,5 V. Ok, das ist natürlich Mist. Aber beherrschbarer. Im Prinzip müssen nur die Widerstände für die Spannungsteiler neu berechnet werden. Jetzt kann man es sich natürlich einfach machen und die naheliegendsten Werte aus der E24-Reihe nehmen. Selbst für gut ausgestattete Widerstandslager zu Hause würde das eine Bestellung bei den üblichen Verdächtigen bedeuten. Dann hat man meistens noch die vermutlich selten genutzten Wert-Überreste in einer Schublade liegen und das Bestücken ist fehleranfälliger. Uncool. Also warum nicht so lange mit den Bauteilwerten jonglieren, bis es eine gute Kombination gibt? Kann man manuell machen, ist aber eher mühsam. Geht auch mit Excel, ist aber auch nicht das beste Tool dafür. Ob JavaScript so wirklich dafür geeignet ist, sei mal dahingestellt - dafür spricht allerdings, dass mittlerweile fast jedes Endgerät mit Farbdisplay eine passende Laufzeitumgebung installiert hat. Herausgekommen ist dieser [//hobbyelektronik.org/tools/komparator/ schlichte Rechner]. Zahlen eingeben und los geht's: {| class="wikitable" ! Bezeichnung || Wert || Kommentar |- | Versorgungsspannung Komparator || 3,3 V || |- | Maximale Eingangsspannung Komparator || 1,8 V || (3,3 - 1,5) V |- | Maximale Signalspannung || 6,8 V || (8,2 - 1,4) V |- | Obere Schwelle || 4,5 V || aus der VBus-Spec |- | Untere Schwelle || 4,0 V || aus der VBus-Spec |- |} Aktuell werden Widerstände aus der E6- und (damit es ein bisschen Mehr Auswahl gibt) E12-Reihe für die Bauteilsuche genutzt. Für die eingegebenen Werte ergibt sich eine schöne Kombination aus der E6-Reihe, die nur drei unterschiedliche Werte benötigt: {| class="wikitable" ! Referenz || Wert |- | R8 || 15 k |- | R5 || 4,7 k |- | R3 || 4,7 k |- | R4 || 2,2 k |- | R2 || 15 k |} Zur Gegenprobe - der Spannungsteiler gibt folgende Spannung aus: <math>(\textrm{8,2 V} - \textrm{1,4 V}) \cdot \frac{\textrm{4,7 k}}{\textrm{4,7 k} + \textrm{15 k}} = \textrm{6,8 V} \cdot \frac{\textrm{4,7}}{\textrm{19,7}} = \textrm{1,62 V}</math> Da ist noch gut Luft zu den Maximal 1,8 V - rechnet man rück, dürfte der Spannungsabfall über den Gleichrichter bis auf 0,65 (für beide Dioden) fallen, um auf eine Eingangsspannung von über 1,8 V am Komparator zu kommen Der Kondensator für den Tiefpass kann übrigens gleich bleiben. Die Grenzfrequenz steigt zwar ein wenig, der Wert ist jedoch weniger kritisch. Daraus ergibt sich folgender Schaltplan: <gallery> Vbuspi_1.2b_assy_sch.png|Schaltplan Version 1.2b </gallery> Die aktualisierte BOM lautet wie folgt: <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2* || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2* || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> <nowiki>*)</nowiki> am besten zwei verwenden und stapeln, damit der Schaltung bei längeren Nachrichten die Puste nicht ausgeht - siehe unten Damit sollte nun der Komparator glücklich sein. Auch in der Simulation in LTspice passen die Schwellen und das Verhalten der Schaltung. Hierzu hatte Stefan folgende Anmerkung: <pre> Nicht gefallen tut mir der C6 von 100pF. Dadurch wird zwar die Referenz stabiler aber die Schwellenumschaltung beim Pegelwechsel wird langsamer. Damit reduziert sich die Störfestigkeit des Eingangssignals. Ich hätte es aber vermutlich auch so gemacht. </pre> Ja, das ist richtig - und auch ich war/bin über den Kondensator nicht so richtig glücklich. Das Bauteil ist meiner Meinung allerdings ein sehr einfacher und effektiver Weg, das beschriebene Problem - besonders im bereits existierenden Design - einfach zu umgehen. Da die Versorgung nicht 100 %ig stabil war, hatte er noch folgenden Ratschlag: <pre> Noch eine Anmerkung zu deiner Kostenreduktion mit dem TS5205 CX533. Ich vermute dass der Ausgangskondensator (C3) nicht passt (ESR zu hoch). LowDrop Regler sind bei zu hohem ESR instabil. Manchmal hilft ein 2ter Kondensator parallel zu C3 (so 10nF bis 100nF) um den Regler stabil zu bekommen. </pre> Was ich versucht habe aber nicht zum gewünschten Erfolg verhalf. Das Problem ist vermutlich eher, dass die Schaltung bei aktivem Optokoppler gänzlich aus den Bulk-Kondensatoren gespeist werden müssen. Da hilft nur mehr Kapazität am Eingang, weswegen als Workaround C5 "aufgedoppelt" werden sollte (Stapeln zweier Kondensatoren). Das ist zwar nicht so richtig schön, aber sollte in den meisten Fällen helfen. Aufgrund der verschiedenen Unzulänglichkeiten - und um den bei manchen Reglern erforderlichen Rückkanal zu haben - gibt es eine verbesserte Version der Hardware: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] f4266b0f4d511aa484ed43ca26d8c0d0be884006 1657 1649 2021-06-11T20:20:30Z Chris 2 /* Einleitung */ wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' '''Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[#Die Enttäuschung - Teil 2|1.2b]] nachzubauen.''' =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8* (siehe unten) || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: * Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. * Mit R1 = 6,8k kann der Low-Pegel für die vom Raspberry Pi verwendeten 3,3 V zu hoch sein. Besser einen Wert ab 12k verwenden =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Leiterkarten= Sorry, aktuell gibt es keine mehr. =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =Kostenreduzierte Variante/v1.2= Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ==Die Enttäuschung== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers]], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ==Die (vermeintliche) Lösung== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} ==Die Enttäuschung - Teil 2== Stefan schickte eine Mail mit einen sehr guten Verbesserungsvorschlag bzw. vielmehr Hinweis auf Fehler: <pre> Ich würde an deiner Stelle bei der 3,3V Schaltung den Spannungsteiler R8/R5 anpassen. An dessen Eingang können ~7V anliegen womit der OP dann 3,5V an seinem Eingang hat. Das ist bei 3,3V Versorgungsspannung etwas über der Spezifikation des verwendeten OPs. </pre> Das ist absolut richtig, die Spannung ist außerhalb der Spec. Der Fehler hat sich mit an Sicherheit grenzender Wahrscheinlichkeit eingeschlichen, weil beim Neudimensionieren der Schaltung nur die Teile berücksichtigt wurden, die direkt an +3V3 hängen. Schaut man noch etwas genauer ins Datenblatt entdeckt man, dass die Eingänge des LM393 für eine korrekte Funktion einen gewissen Abstand zu V+ haben müssen. Bei der Variante von TI sind das VDD - 1,5 V. Ok, das ist natürlich Mist. Aber beherrschbarer. Im Prinzip müssen nur die Widerstände für die Spannungsteiler neu berechnet werden. Jetzt kann man es sich natürlich einfach machen und die naheliegendsten Werte aus der E24-Reihe nehmen. Selbst für gut ausgestattete Widerstandslager zu Hause würde das eine Bestellung bei den üblichen Verdächtigen bedeuten. Dann hat man meistens noch die vermutlich selten genutzten Wert-Überreste in einer Schublade liegen und das Bestücken ist fehleranfälliger. Uncool. Also warum nicht so lange mit den Bauteilwerten jonglieren, bis es eine gute Kombination gibt? Kann man manuell machen, ist aber eher mühsam. Geht auch mit Excel, ist aber auch nicht das beste Tool dafür. Ob JavaScript so wirklich dafür geeignet ist, sei mal dahingestellt - dafür spricht allerdings, dass mittlerweile fast jedes Endgerät mit Farbdisplay eine passende Laufzeitumgebung installiert hat. Herausgekommen ist dieser [//hobbyelektronik.org/tools/komparator/ schlichte Rechner]. Zahlen eingeben und los geht's: {| class="wikitable" ! Bezeichnung || Wert || Kommentar |- | Versorgungsspannung Komparator || 3,3 V || |- | Maximale Eingangsspannung Komparator || 1,8 V || (3,3 - 1,5) V |- | Maximale Signalspannung || 6,8 V || (8,2 - 1,4) V |- | Obere Schwelle || 4,5 V || aus der VBus-Spec |- | Untere Schwelle || 4,0 V || aus der VBus-Spec |- |} Aktuell werden Widerstände aus der E6- und (damit es ein bisschen Mehr Auswahl gibt) E12-Reihe für die Bauteilsuche genutzt. Für die eingegebenen Werte ergibt sich eine schöne Kombination aus der E6-Reihe, die nur drei unterschiedliche Werte benötigt: {| class="wikitable" ! Referenz || Wert |- | R8 || 15 k |- | R5 || 4,7 k |- | R3 || 4,7 k |- | R4 || 2,2 k |- | R2 || 15 k |} Zur Gegenprobe - der Spannungsteiler gibt folgende Spannung aus: <math>(\textrm{8,2 V} - \textrm{1,4 V}) \cdot \frac{\textrm{4,7 k}}{\textrm{4,7 k} + \textrm{15 k}} = \textrm{6,8 V} \cdot \frac{\textrm{4,7}}{\textrm{19,7}} = \textrm{1,62 V}</math> Da ist noch gut Luft zu den Maximal 1,8 V - rechnet man rück, dürfte der Spannungsabfall über den Gleichrichter bis auf 0,65 (für beide Dioden) fallen, um auf eine Eingangsspannung von über 1,8 V am Komparator zu kommen Der Kondensator für den Tiefpass kann übrigens gleich bleiben. Die Grenzfrequenz steigt zwar ein wenig, der Wert ist jedoch weniger kritisch. Daraus ergibt sich folgender Schaltplan: <gallery> Vbuspi_1.2b_assy_sch.png|Schaltplan Version 1.2b </gallery> Die aktualisierte BOM lautet wie folgt: <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2* || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2* || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> <nowiki>*)</nowiki> am besten zwei verwenden und stapeln, damit der Schaltung bei längeren Nachrichten die Puste nicht ausgeht - siehe unten Damit sollte nun der Komparator glücklich sein. Auch in der Simulation in LTspice passen die Schwellen und das Verhalten der Schaltung. Hierzu hatte Stefan folgende Anmerkung: <pre> Nicht gefallen tut mir der C6 von 100pF. Dadurch wird zwar die Referenz stabiler aber die Schwellenumschaltung beim Pegelwechsel wird langsamer. Damit reduziert sich die Störfestigkeit des Eingangssignals. Ich hätte es aber vermutlich auch so gemacht. </pre> Ja, das ist richtig - und auch ich war/bin über den Kondensator nicht so richtig glücklich. Das Bauteil ist meiner Meinung allerdings ein sehr einfacher und effektiver Weg, das beschriebene Problem - besonders im bereits existierenden Design - einfach zu umgehen. Da die Versorgung nicht 100 %ig stabil war, hatte er noch folgenden Ratschlag: <pre> Noch eine Anmerkung zu deiner Kostenreduktion mit dem TS5205 CX533. Ich vermute dass der Ausgangskondensator (C3) nicht passt (ESR zu hoch). LowDrop Regler sind bei zu hohem ESR instabil. Manchmal hilft ein 2ter Kondensator parallel zu C3 (so 10nF bis 100nF) um den Regler stabil zu bekommen. </pre> Was ich versucht habe aber nicht zum gewünschten Erfolg verhalf. Das Problem ist vermutlich eher, dass die Schaltung bei aktivem Optokoppler gänzlich aus den Bulk-Kondensatoren gespeist werden müssen. Da hilft nur mehr Kapazität am Eingang, weswegen als Workaround C5 "aufgedoppelt" werden sollte (Stapeln zweier Kondensatoren). Das ist zwar nicht so richtig schön, aber sollte in den meisten Fällen helfen. Aufgrund der verschiedenen Unzulänglichkeiten - und um den bei manchen Reglern erforderlichen Rückkanal zu haben - gibt es eine verbesserte Version der Hardware: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] daa38bacec28d5e1d26e817770c6797c41ad8f00 Hobbyelektronik.org:Impressum 4 4 1641 1598 2021-03-21T22:12:08Z Chris 2 wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org For those who don't speak German: feel free to write me in English! Im Normalfall antworte ich innerhalb von 1-3 Tagen. Solltest du innerhalb einer Woche keine Antwort bekommen, prüfe bitte deinen Spamfilter oder schicke eine Erinnerung, manchmal geht auch bei mir etwas unter. E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung im Schnitt nur eine Konversation in 2-3 Jahren verschlüsselt stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Kommerzielle Anfragen= In en meisten Fällen lautet die Antwort schlicht "Nein". Wie weiter unten steht habe ich kein Interesse an Werbung oder "kommerzielle Kooperation". Entsprechende Anfragen werden ignoriert. Auch habe ich wenig Interesse, in meiner Freizeit an kommerziellen Projekten oder Produkten zu arbeiten. Dazu fehlen mir einfach Zeit und Ressourcen. Nicht unbedingt technisch, sondern vielmehr organisatorisch. Produkte auf den Markt zu bringen ist deutlich mehr als Hardware zusammenklatschen und vielleicht noch "ein bisschen" Software dafür zu entwickeln. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schneller (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzübung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nichts durch finanzielle Mittel beeinflusst. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) 1c946fe60a4c6a61f7882133c8557e62af5298dd 1645 1641 2021-03-30T15:31:57Z Chris 2 /* Kommerzielle Anfragen */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org For those who don't speak German: feel free to write me in English! Im Normalfall antworte ich innerhalb von 1-3 Tagen. Solltest du innerhalb einer Woche keine Antwort bekommen, prüfe bitte deinen Spamfilter oder schicke eine Erinnerung, manchmal geht auch bei mir etwas unter. E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung im Schnitt nur eine Konversation in 2-3 Jahren verschlüsselt stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Kommerzielle Anfragen= In den meisten Fällen lautet die Antwort schlicht "Nein". Wie weiter unten steht habe ich kein Interesse an Werbung oder "kommerzieller Kooperation". Entsprechende Anfragen werden ignoriert. Auch habe ich wenig Interesse, in meiner Freizeit an kommerziellen Projekten oder Produkten zu arbeiten. Dazu fehlen mir einfach Zeit und Ressourcen. Nicht unbedingt technisch, sondern vielmehr organisatorisch. Produkte auf den Markt zu bringen ist deutlich mehr als Hardware zusammenzuklatschen und vielleicht noch "ein bisschen" Software dafür zu entwickeln. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schneller (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzübung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nichts durch finanzielle Mittel beeinflusst. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) 072bd6b4c8d761293446346d2912d539cd70d6e3 VBus-Decoder 0 120 1646 1638 2021-06-08T19:46:09Z Chris 2 /* Adapter für den Raspberry Pi */ Typo wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Allerdings scheint Resol bei ein paar Reglern eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden - was mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Achtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] bcacfa86ad32213d0be66e10e6e707ecc1d45a0b 1659 1646 2021-07-04T20:07:01Z Chris 2 /* Hardware-Schnittstelle */ Wording wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Achtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 30b461118936deddb9cf52862caf30788f08c32b 1661 1659 2021-07-04T20:13:32Z Chris 2 /* Software */ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Achtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] Oliver hat basierend auf dem Code von Nicki eine Schnittstelle zur [https://www.volkszaehler.org/ Volkszähler]-Middleware gebaut: <pre> Der Code nutzt die Resol-Decoder-Lib von Nicki, die ist auch mit dabei. In der config.py stellt man die Adresse der Middleware in seinem Netzwerk, sowie die UUID der Kanäle ein, damit man die Daten referenzieren kann. (Zum Test kann man auch simulierte Daten nutzen, oder die Ausgabe in ein File schreiben lassen) </pre> * [[Datei:Vbus_volkszaehler.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] aacd4479581ac4dd6373e3e44139324d65d89b00 1662 1661 2021-07-04T20:13:49Z Chris 2 /* Python */ Umbruch wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Achtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] Oliver hat basierend auf dem Code von Nicki eine Schnittstelle zur [https://www.volkszaehler.org/ Volkszähler]-Middleware gebaut: <pre> Der Code nutzt die Resol-Decoder-Lib von Nicki, die ist auch mit dabei. In der config.py stellt man die Adresse der Middleware in seinem Netzwerk, sowie die UUID der Kanäle ein, damit man die Daten referenzieren kann. (Zum Test kann man auch simulierte Daten nutzen, oder die Ausgabe in ein File schreiben lassen) </pre> * [[Datei:Vbus_volkszaehler.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] d6219fb044fbcfb062395b454a0075d1ca7b25a1 VBus-Decoder/Adapter für den Raspberry Pi v1.3 0 715 1647 1637 2021-06-08T19:47:34Z Chris 2 wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Who's perfect? Beim [[VBus-Decoder/Adapter_für_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] (und auch dem [[VBus-Decoder/Adapter_Nano|Nano]]) gibt es ein paar Unzulänglichkeiten, die jeweils ein Makeover der Leiterkarte erfordern. Da die Beliebtheit des Raspberry Pis deutlich größer als ein Arghduino für solche Anwendungen ist, gibt es hierfür zuerst (oder überhaupt) eine neue Version. Konkret handelt es sich um folgende Probleme, die mit der neuen Version behoben werden sollen: * Keine gestapelten Bauteile mehr * Hinreichend Eingangskapazität für mehr Zuverlässigkeit * Größere Bauteile zur einfacheren Bestückung * Rückkanal, um den Regler aktiv abfragen und parametrieren zu können =Änderungen= Aus dem MLCC-Kondensator wurde ein Elektrolyt, aktuell 100 µF, lässt sich bei Bedarf aber noch ein bisschen vergrößern. Dieser wird nun über einen Widerstand am Gleichrichter angebunden um den Ladestrom (und dadurch die Spannungseinbrüche auf dem Bus) zu verkleinern. Ob die Kombination aus 470 Ohm und 100 Mikrofarad gut ist, muss sich noch zeigen. Beim Spannungsregler ist der 3,3 V-Typ gekommen um zu bleiben. Dieser bietet neben dem etwas niedrigeren Preis den Vorteil, dass er auf der Eingangsseite einen größeren "Headroom" hat. Die Neudimensionierung der Spannungsteiler basiert auf den Berechnungen von [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]]. Als Bestückoption gibt es nun auch einen Jumper, mit dem die Versorgung des Komparators ausgewählt werden kann - sollten die Referenzspannungen nach dem 3,3 V-Regler doch zu knapp werden, kann die Eingangsspannung des LDO verwendet werden. Offen ist natürlich, ob der zu erwartende Ripple in die Suppe spuckt. Die diskreten Bauteile sind nun alle im 0805-Package, dadurch wurden weite Teile des Layouts umgeworfen. Wer möchte, kann natürlich auch welche im 0603-Package (oder mit ein bisschen Wollen sollte auch 1206 gehen) auf die Footprints packen. Gänzlich neu ist der Rückkanal, die Dimensionierung dessen Bauteile erfolgte mit dem feuchten Finger in den Wind gehalten. Es ist eigentlich nichts besonderes zu erwarten, bei Bedarf kann allerdings einfach mit den Bauteilen gespielt werden. Die Änderungen kommen allerdings mit ein paar Kompromissen: * Die Leiterkarte wurde ein bisschen größer * Die Power-LED für den VBus ist rausgefallen (kein Platz, unnötiger Verbraucher) * Bei der Nutzung des Rückkanals ist... ** die Leiterkarte auf dem Pi Zero nur mit "Überhang" verwendbar ** keine galvanische Trennung möglich <gallery> Vbuspi_1.3_assy_sch.png | Schaltplan Vbuspi_1.3_assy_brd.png | Layout </gallery> =BOM= <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 470 || R0805 || RND 0805 1 470 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0805 || RND 0805 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_opto_sch.png | Bestückungsplan für optoisolierte Variante </gallery> </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X3 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 470 || R0805 || RND 0805 1 470 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 3 || Q1, Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_direct_sch.png | Bestückungsplan für unisolierte Variante </gallery> </tab> </tabs> =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbuspi_1.3.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] ed2a94e2cfeebade79af83ff03c73ba68d660ee3 1653 1647 2021-06-11T20:04:07Z Chris 2 /* BOM */ BOM aktualisiert wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Who's perfect? Beim [[VBus-Decoder/Adapter_für_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] (und auch dem [[VBus-Decoder/Adapter_Nano|Nano]]) gibt es ein paar Unzulänglichkeiten, die jeweils ein Makeover der Leiterkarte erfordern. Da die Beliebtheit des Raspberry Pis deutlich größer als ein Arghduino für solche Anwendungen ist, gibt es hierfür zuerst (oder überhaupt) eine neue Version. Konkret handelt es sich um folgende Probleme, die mit der neuen Version behoben werden sollen: * Keine gestapelten Bauteile mehr * Hinreichend Eingangskapazität für mehr Zuverlässigkeit * Größere Bauteile zur einfacheren Bestückung * Rückkanal, um den Regler aktiv abfragen und parametrieren zu können =Änderungen= Aus dem MLCC-Kondensator wurde ein Elektrolyt, aktuell 100 µF, lässt sich bei Bedarf aber noch ein bisschen vergrößern. Dieser wird nun über einen Widerstand am Gleichrichter angebunden um den Ladestrom (und dadurch die Spannungseinbrüche auf dem Bus) zu verkleinern. Ob die Kombination aus 470 Ohm und 100 Mikrofarad gut ist, muss sich noch zeigen. Beim Spannungsregler ist der 3,3 V-Typ gekommen um zu bleiben. Dieser bietet neben dem etwas niedrigeren Preis den Vorteil, dass er auf der Eingangsseite einen größeren "Headroom" hat. Die Neudimensionierung der Spannungsteiler basiert auf den Berechnungen von [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]]. Als Bestückoption gibt es nun auch einen Jumper, mit dem die Versorgung des Komparators ausgewählt werden kann - sollten die Referenzspannungen nach dem 3,3 V-Regler doch zu knapp werden, kann die Eingangsspannung des LDO verwendet werden. Offen ist natürlich, ob der zu erwartende Ripple in die Suppe spuckt. Die diskreten Bauteile sind nun alle im 0805-Package, dadurch wurden weite Teile des Layouts umgeworfen. Wer möchte, kann natürlich auch welche im 0603-Package (oder mit ein bisschen Wollen sollte auch 1206 gehen) auf die Footprints packen. Gänzlich neu ist der Rückkanal, die Dimensionierung dessen Bauteile erfolgte mit dem feuchten Finger in den Wind gehalten. Es ist eigentlich nichts besonderes zu erwarten, bei Bedarf kann allerdings einfach mit den Bauteilen gespielt werden. Die Änderungen kommen allerdings mit ein paar Kompromissen: * Die Leiterkarte wurde ein bisschen größer * Die Power-LED für den VBus ist rausgefallen (kein Platz, unnötiger Verbraucher) * Bei der Nutzung des Rückkanals ist... ** die Leiterkarte auf dem Pi Zero nur mit "Überhang" verwendbar ** keine galvanische Trennung möglich <gallery> Vbuspi_1.3_assy_sch.png | Schaltplan Vbuspi_1.3_assy_brd.png | Layout </gallery> =BOM= <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 15k || R0805 || RND 0805 1 15K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_opto_sch.png | Bestückungsplan für optoisolierte Variante </gallery> </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X3 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 3 || Q1, Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_direct_sch.png | Bestückungsplan für unisolierte Variante </gallery> </tab> </tabs> =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbuspi_1.3.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 23539fcc9f29f23cc2fd9b599837f90925ce879d 1656 1653 2021-06-11T20:17:30Z Chris 2 wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Who's perfect? Beim [[VBus-Decoder/Adapter_für_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] (und auch dem [[VBus-Decoder/Adapter_Nano|Nano]]) gibt es ein paar Unzulänglichkeiten, die jeweils ein Makeover der Leiterkarte erfordern. Da die Beliebtheit des Raspberry Pis deutlich größer als ein Arghduino für solche Anwendungen ist, gibt es hierfür zuerst (oder überhaupt) eine neue Version. Konkret handelt es sich um folgende Probleme, die mit der neuen Version behoben werden sollen: * Keine gestapelten Bauteile mehr * Hinreichend Eingangskapazität für mehr Zuverlässigkeit * Größere Bauteile zur einfacheren Bestückung * Rückkanal, um den Regler aktiv abfragen und parametrieren zu können =Änderungen= Aus dem MLCC-Kondensator wurde ein Elektrolyt, aktuell 100 µF, lässt sich bei Bedarf aber noch ein bisschen vergrößern. Dieser wird nun über einen Widerstand am Gleichrichter angebunden um den Ladestrom (und dadurch die Spannungseinbrüche auf dem Bus) zu verkleinern. Ob die Kombination aus 470 Ohm und 100 Mikrofarad gut ist, muss sich noch zeigen. Beim Spannungsregler ist der 3,3 V-Typ gekommen um zu bleiben. Dieser bietet neben dem etwas niedrigeren Preis den Vorteil, dass er auf der Eingangsseite einen größeren "Headroom" hat. Die Neudimensionierung der Spannungsteiler basiert auf den Berechnungen von [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]]. Als Bestückoption gibt es nun auch einen Jumper, mit dem die Versorgung des Komparators ausgewählt werden kann - sollten die Referenzspannungen nach dem 3,3 V-Regler doch zu knapp werden, kann die Eingangsspannung des LDO verwendet werden. Offen ist natürlich, ob der zu erwartende Ripple in die Suppe spuckt. Die diskreten Bauteile sind nun alle im 0805-Package, dadurch wurden weite Teile des Layouts umgeworfen. Wer möchte, kann natürlich auch welche im 0603-Package (oder mit ein bisschen Wollen sollte auch 1206 gehen) auf die Footprints packen. Gänzlich neu ist der Rückkanal, die Dimensionierung dessen Bauteile erfolgte mit dem feuchten Finger in den Wind gehalten. Es ist eigentlich nichts besonderes zu erwarten, bei Bedarf kann allerdings einfach mit den Bauteilen gespielt werden. Die Änderungen kommen allerdings mit ein paar Kompromissen: * Die Leiterkarte wurde ein bisschen größer * Die Power-LED für den VBus ist rausgefallen (kein Platz, unnötiger Verbraucher) * Bei der Nutzung des Rückkanals ist... ** die Leiterkarte auf dem Pi Zero nur mit "Überhang" verwendbar ** keine galvanische Trennung möglich <gallery> Vbuspi_1.3_assy_sch.png | Schaltplan Vbuspi_1.3_assy_brd.png | Layout </gallery> =BOM= <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 15k || R0805 || RND 0805 1 15K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_opto_sch.png | Bestückungsplan für optoisolierte Variante </gallery> </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X3 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 3 || Q1, Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_direct_sch.png | Bestückungsplan für unisolierte Variante </gallery> </tab> </tabs> =Hinweise= * R1 sollte einen Wert ab ca. 12k haben, damit der Low-Pegel auch wirklich 0 erreicht. * Aktuell ist nur die optoisolierte Version getestet * selbst bei "nur" 1,2 mm dickem FR4 würde ich nicht empfehlen, die Leiterkarte an den perforierten Kanten zu brechen. Besser sägen oder mit einer Trennscheibe arbeiten. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbuspi_1.3.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 9b385be7e8ee005eae5cc49320261bfc8c532562 1663 1656 2021-07-06T17:39:46Z Chris 2 /* Hinweise */ wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Who's perfect? Beim [[VBus-Decoder/Adapter_für_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] (und auch dem [[VBus-Decoder/Adapter_Nano|Nano]]) gibt es ein paar Unzulänglichkeiten, die jeweils ein Makeover der Leiterkarte erfordern. Da die Beliebtheit des Raspberry Pis deutlich größer als ein Arghduino für solche Anwendungen ist, gibt es hierfür zuerst (oder überhaupt) eine neue Version. Konkret handelt es sich um folgende Probleme, die mit der neuen Version behoben werden sollen: * Keine gestapelten Bauteile mehr * Hinreichend Eingangskapazität für mehr Zuverlässigkeit * Größere Bauteile zur einfacheren Bestückung * Rückkanal, um den Regler aktiv abfragen und parametrieren zu können =Änderungen= Aus dem MLCC-Kondensator wurde ein Elektrolyt, aktuell 100 µF, lässt sich bei Bedarf aber noch ein bisschen vergrößern. Dieser wird nun über einen Widerstand am Gleichrichter angebunden um den Ladestrom (und dadurch die Spannungseinbrüche auf dem Bus) zu verkleinern. Ob die Kombination aus 470 Ohm und 100 Mikrofarad gut ist, muss sich noch zeigen. Beim Spannungsregler ist der 3,3 V-Typ gekommen um zu bleiben. Dieser bietet neben dem etwas niedrigeren Preis den Vorteil, dass er auf der Eingangsseite einen größeren "Headroom" hat. Die Neudimensionierung der Spannungsteiler basiert auf den Berechnungen von [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]]. Als Bestückoption gibt es nun auch einen Jumper, mit dem die Versorgung des Komparators ausgewählt werden kann - sollten die Referenzspannungen nach dem 3,3 V-Regler doch zu knapp werden, kann die Eingangsspannung des LDO verwendet werden. Offen ist natürlich, ob der zu erwartende Ripple in die Suppe spuckt. Die diskreten Bauteile sind nun alle im 0805-Package, dadurch wurden weite Teile des Layouts umgeworfen. Wer möchte, kann natürlich auch welche im 0603-Package (oder mit ein bisschen Wollen sollte auch 1206 gehen) auf die Footprints packen. Gänzlich neu ist der Rückkanal, die Dimensionierung dessen Bauteile erfolgte mit dem feuchten Finger in den Wind gehalten. Es ist eigentlich nichts besonderes zu erwarten, bei Bedarf kann allerdings einfach mit den Bauteilen gespielt werden. Die Änderungen kommen allerdings mit ein paar Kompromissen: * Die Leiterkarte wurde ein bisschen größer * Die Power-LED für den VBus ist rausgefallen (kein Platz, unnötiger Verbraucher) * Bei der Nutzung des Rückkanals ist... ** die Leiterkarte auf dem Pi Zero nur mit "Überhang" verwendbar ** keine galvanische Trennung möglich <gallery> Vbuspi_1.3_assy_sch.png | Schaltplan Vbuspi_1.3_assy_brd.png | Layout </gallery> =BOM= <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 15k || R0805 || RND 0805 1 15K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_opto_sch.png | Bestückungsplan für optoisolierte Variante </gallery> </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X3 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 3 || Q1, Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_direct_sch.png | Bestückungsplan für unisolierte Variante </gallery> </tab> </tabs> =Hinweise= * '''Bitte nur die Bauteile bestücken, die in der BOM für die jeweilige Variante angegeben sind. Mehr hilft nicht mehr, sondern kann zu fehlerhafter Funktion führen.''' * R14 in der Direktvariante sollte nicht bestückt werden oder zumindest in Pull-up-Konfiguration umgebaut werden. Sonst kann (und wird) es passieren, dass der VBus bei nicht angeschlossenem Tx dauerhaft kurzgeschlossen wird. (Danke an Heiko für den Hinweis!) * R1 sollte einen Wert ab ca. 12k haben, damit der Low-Pegel auch wirklich 0 erreicht. * Aktuell ist nur die optoisolierte Version getestet * selbst bei "nur" 1,2 mm dickem FR4 würde ich nicht empfehlen, die Leiterkarte an den perforierten Kanten zu brechen. Besser sägen oder mit einer Trennscheibe arbeiten. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbuspi_1.3.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 35978e0d7cedb7c3fcfb741eb567fe02b1afae73 1664 1663 2021-07-06T17:40:09Z Chris 2 /* Hinweise */ Wording wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Who's perfect? Beim [[VBus-Decoder/Adapter_für_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] (und auch dem [[VBus-Decoder/Adapter_Nano|Nano]]) gibt es ein paar Unzulänglichkeiten, die jeweils ein Makeover der Leiterkarte erfordern. Da die Beliebtheit des Raspberry Pis deutlich größer als ein Arghduino für solche Anwendungen ist, gibt es hierfür zuerst (oder überhaupt) eine neue Version. Konkret handelt es sich um folgende Probleme, die mit der neuen Version behoben werden sollen: * Keine gestapelten Bauteile mehr * Hinreichend Eingangskapazität für mehr Zuverlässigkeit * Größere Bauteile zur einfacheren Bestückung * Rückkanal, um den Regler aktiv abfragen und parametrieren zu können =Änderungen= Aus dem MLCC-Kondensator wurde ein Elektrolyt, aktuell 100 µF, lässt sich bei Bedarf aber noch ein bisschen vergrößern. Dieser wird nun über einen Widerstand am Gleichrichter angebunden um den Ladestrom (und dadurch die Spannungseinbrüche auf dem Bus) zu verkleinern. Ob die Kombination aus 470 Ohm und 100 Mikrofarad gut ist, muss sich noch zeigen. Beim Spannungsregler ist der 3,3 V-Typ gekommen um zu bleiben. Dieser bietet neben dem etwas niedrigeren Preis den Vorteil, dass er auf der Eingangsseite einen größeren "Headroom" hat. Die Neudimensionierung der Spannungsteiler basiert auf den Berechnungen von [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]]. Als Bestückoption gibt es nun auch einen Jumper, mit dem die Versorgung des Komparators ausgewählt werden kann - sollten die Referenzspannungen nach dem 3,3 V-Regler doch zu knapp werden, kann die Eingangsspannung des LDO verwendet werden. Offen ist natürlich, ob der zu erwartende Ripple in die Suppe spuckt. Die diskreten Bauteile sind nun alle im 0805-Package, dadurch wurden weite Teile des Layouts umgeworfen. Wer möchte, kann natürlich auch welche im 0603-Package (oder mit ein bisschen Wollen sollte auch 1206 gehen) auf die Footprints packen. Gänzlich neu ist der Rückkanal, die Dimensionierung dessen Bauteile erfolgte mit dem feuchten Finger in den Wind gehalten. Es ist eigentlich nichts besonderes zu erwarten, bei Bedarf kann allerdings einfach mit den Bauteilen gespielt werden. Die Änderungen kommen allerdings mit ein paar Kompromissen: * Die Leiterkarte wurde ein bisschen größer * Die Power-LED für den VBus ist rausgefallen (kein Platz, unnötiger Verbraucher) * Bei der Nutzung des Rückkanals ist... ** die Leiterkarte auf dem Pi Zero nur mit "Überhang" verwendbar ** keine galvanische Trennung möglich <gallery> Vbuspi_1.3_assy_sch.png | Schaltplan Vbuspi_1.3_assy_brd.png | Layout </gallery> =BOM= <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 15k || R0805 || RND 0805 1 15K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_opto_sch.png | Bestückungsplan für optoisolierte Variante </gallery> </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X3 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 3 || Q1, Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_direct_sch.png | Bestückungsplan für unisolierte Variante </gallery> </tab> </tabs> =Hinweise= * '''Bitte nur die Bauteile bestücken, die in der BOM für die jeweilige Variante angegeben sind. Mehr hilft nicht mehr, sondern kann zu Fehlfunktionen führen.''' * R14 in der Direktvariante sollte nicht bestückt werden oder zumindest in Pull-up-Konfiguration umgebaut werden. Sonst kann (und wird) es passieren, dass der VBus bei nicht angeschlossenem Tx dauerhaft kurzgeschlossen wird. (Danke an Heiko für den Hinweis!) * R1 sollte einen Wert ab ca. 12k haben, damit der Low-Pegel auch wirklich 0 erreicht. * Aktuell ist nur die optoisolierte Version getestet * selbst bei "nur" 1,2 mm dickem FR4 würde ich nicht empfehlen, die Leiterkarte an den perforierten Kanten zu brechen. Besser sägen oder mit einer Trennscheibe arbeiten. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbuspi_1.3.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 60e5cf4c5c67fe43e9a3558d75f3303a2667702f USB-Fußtaster 0 623 1648 1550 2021-06-08T19:52:13Z Chris 2 /* Firmware */ wikitext text/x-wiki [[Datei:Footswitch.jpg|thumb|Fertig aufgebauter Fußtaster]] "Schau Mama, freihändig!" Wer kennt das nicht? Man muss auf mehreren Leiterkarten verschiedene Spannungen messen. Üblicherweise läuft es dann wie folgt ab: # Messspitzen platzieren # Wert vom Messgerät ablesen # Messspitzen ablegen und zum PC umdrehen # Messwert eintippen # Zurückdrehen, Messspitzen wieder in die Hände nehmen # Nochmal nachschauen, welcher Messpunkt jetzt dran ist # Wiederholen Ab und zu mischt sich dann das erneute Messen ein, weil ein Wert unplausibel ist und man entweder einen Zahlendreher drin oder schneller getippt als gedacht hat. Unterm Strich ist es auf jeden Fall sehr zeitraubend und nervig. Gleichzeitig baumeln die Füße unbeteiligt am Stuhl herunter. Die meisten Messgeräte (und anderes Laborequipment) lassen sich über den PC kontrollieren, warum also nicht gleich die richtigen Werte z. B. nach Excel transferieren? Nur irgendwie muss man den Prozess anstoßen... =Die schnelle Lösung= Tastatur ist blöd, also muss eine andere Eingabemöglichkeit her. Ein Taster und eine Projektbox ist schnell gefunden, Loch in die Box und ein paar große Schrauben dazu (damit sie nicht gleich abhaut) und fertig ist der improvisierte Fußtaster. Nur wie kommt die Info in den PC? Die serielle Schnittstelle hat neben Rx und Tx oft auch Steuerleitungen – aus den alten Tagen, in denen Modems noch so richtig langsam waren. Diese lassen sich in so ziemlich jeder Programmiersprache kontrollieren und abfragen. Ein FT232 liegt auch noch herum, also Taster angelötet und los geht’s! Das Programm ist in Python geschrieben, pollt die CTS-Leitung und sobald diese low wird, wird per pyVisa den Multimeter der aktuelle Messwert entlockt, passend formatiert und mit dem Keyboard-Modul "ausgetippt". Damit die Augen am Mikroskop bleiben können, wird zudem ein kurzer Piepton ausgegeben. Sehr viel Spaß für wenig Geld. Leider muss man bei jeder Benutzung schauen, welcher COM-Port dem Adapter zugeordnet wurde und ob dieser auch wirklich im Script steht. =Die schöne Lösung= Eines Tages brachte mein Kollege einen kleinen Pappkarton vom [https://www.pollin.de Ramschmax] mit, Inhalt: [https://www.pollin.de/p/fusstaster-pfs-135a-10-a-250-v-420705 420705]. Ein Gusseiserner Fußtaster mit schönem Klick-Klack-Mikroschalter. Der hat etwas Besseres als den schnöden UART-Adapter mit Zwillingslitze verdient – endlich wieder eine schöne Anwendung für [https://www.obdev.at/vusb/ V-USB]! Was soll das Teil können? Am besten natürlich so viel wie möglich, damit es vielleicht sogar als "Adaptive Controller" dienen kann. Deshalb habe ich mich dafür entschieden, einen Multidevice-Ansatz zu fahren. Das umfasst aktuell: * Generisches USB-HID * Einzeltasten-Tastatur * Makro-Tastatur * Joystick =Hardware= Die Hardware könnte nicht einfacher sein - sie entspricht größtenteils dem [https://www.obdev.at/products/vusb/easylogger.html Easylogger]-Beispielprojekt, nur dass anstelle der automatischen Oszillator-Kalibrierung ein externer Quarz verwendet wird. Hintergrund hierfür ist, dass das [[SNES-Joypad]], das sich selbst kalibriert (oder zumindest sollte), am RetroPie beim Booten oft nicht erkannt wird. Kann aber auch gut sein, dass es sich um einen Bug in meiner Firmware handelt. Die Bauteile sind - abgesehen vom Quarz und Mikrocontroller in SMD-Bauform. Als MCU werkelt fürs Erste ein ATtiny85, der später noch herunterskaliert werden kann. Die Wahl auf das DIP-Gehäuse fiel, um ohne Löten die Firmware herunterzuladen. Mit Quarz als Taktquelle bleibt noch ein "richtiger" IO übrig (sofern man den Reset-Pin nicht deaktiviert) - mehr braucht man nicht. Eine eigens designte Leiterkarte ist aufgrund der Einfachheit der Schaltung völlig unnötig, aber es war noch Platz auf dem Panel... <gallery> footswitch 1.0 sch.png|Schaltplan footswitch 1.0 top.png|Bestückungsplan Oberseite footswitch 1.0 bot.png|Bestückungsplan Unterseite footswitch 1.0 assy.jpg|Aufgebaute Leiterkarte </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV3 || || MA03-1 || |- | 1 || SV1 || || MA04-1 || GC 2212-EU030 |- | 1 || C1 || 100n || C0603 || X7R-G0603 100N |- | 1 || C4 || 10u || C0805 || KEM X7R0805 10U |- | 1 || Q1 || 12M || HC49U-V || 12,0000-HC49U-S |- | 1 || R11 || 150 || R0603 || RND 0603 1 150 |- | 1 || C5 || 150n || C0603 || X7R 0603FCE 150N |- | 2 || C2, C3 || 22p || C0603 || RND 150MT18N2202 |- | 1 || R3 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || R10 || 4k7 || R0603 || RND 0603 1 4,7k |- | 2 || R1, R2 || 68 || R0603 || RND 0603 1 68 |- | 1 || IC1 || ATTINY 85-20 PU || DIL08 || ATTINY 85-20 PU |- | 2 || D1, D2 || BZX84C3V6 || SOT23 || SMD ZD 3,6 |} Leider stellte sich erst zu spät heraus, dass die Leiterkarte ein bisschen zu groß ist, um sie an der eigentlich vorgesehenen Stelle zu montieren. Man kann sie zwar ein bisschen schräg anschrauben und von der Ecke noch etwas Material wegnehmen, aber dann ist die USB-Leitung auch wieder im Weg. Das Design ist also nicht so richtig geglückt... Aber kein Problem, dass man nicht mit ein bisschen Schrumpfschlauch lösen könnte: <gallery> footswitch 1.0 designflaw 1.jpg|Dort sollte die Leiterkarte hin footswitch 1.0 designflaw 2.jpg|...und hier ist sie footswitch 1.0 designflaw 3.jpg|weitere Perspektive </gallery> Der Schirm ist übrigens auf ein Stück Leitung gecrimpt, das wiederum an die Halterung des Tasters gelötet ist. =Firmware= {{Infobox AVR | Typ = ATtiny85 | Takt = 12 | FuseH = D7 | FuseL = DE | FuseE = FF }} Die Firmware ist mehr oder weniger viergeteilt, entsprechend den verschiedenen Modi. Hierfür gibt es mehrere Gründe: * die freien VID/PID-Paare sind auf die verschiedenen Funktionen beschränkt und es lässt sich nicht zweifelsfrei sagen, ob Multi-Endpoint-Konfigurationen erlaubt sind * Die Fragmentierung macht den Code (teilweise) einfacher und übersichtlicher * Keinerlei Treiberprobleme (es gibt wohl Betriebssysteme, die sich an Multi-Endpoint verschlucken) * Es ist nicht ganz so üblich und in der Implementierung interessanter Nach dem Reset liest die Firmware den zu verwendenden Modus aus dem EEPROM. Ist diese ungültig oder der IO des Tasters auf Masse gezogen, wird der auf Generisches HID gesetzt. Gegenüber des USB-Treibers wird nun auch der Pointer für die USB-Deskriptoren gesetzt (die sich wiederum im Flash befinden). Anschließend läuft die Initialisierung der unterschiedlichen Modi und es wird in die entsprechende Endlosschleife gesprungen. Als USB VID/PID-Paare werden von obdev frei zur Verfügung gestellten verwendet: * HID: 0x16C0/0x27D9 * Tastatur: 0x16C0/0x27DB * Gamepad: 0x16C0/0x27DC Im Grunde ist das alles kein Hexenwerk, allerdings haben die "Dynamisierung" der USB-Deskriptoren einiges an (auf dem Attiny schwierige) Fehlersuche gekostet. Über Manche Dinge, wie z. B. wie man die verschiedenen Deskriptoren den Anfragen zuordnet, ist die Dokumentation leider etwas vage (oder ich habe sie nicht richtig gelesen/falsch gesucht). Auch lässt sich die Firmware noch ziemlich optimieren, das gesteckte Ziel wäre, dass sie auf den ATtiny45 passt. Aktuell ist hauptsächlich die RAM-Belegung ein Problem (und noch nicht optimal). =Konfiguration= Um die Konfiguration des Fußtasters ändern zu können, muss er sich in Modus 2 (Generisches HID) befinden. Sollte dieser Modus nicht aktiv sein, kann er erreicht werden indem der Taster gedrückt wird, während der USB-Stecker verbunden wird. In den Report-Beispielen werden stets hexadezimale Zahlen verwendet. Angaben mit <code>xx</code> sind beliebig bzw. müssen ignoriert werden. ==Keycodes== Bevor auf die verschiedenen Funktionen im Detail eingegangen wird, ein paar Worte zu den Keycodes: Tastaturen sind seit jeher ziemlich einfach gestrickt. So "weiß" der Controller der Tastatur zwar an welcher Position eine Taste gedrückt wird, aber nicht welches Layout sie vertritt - dies wird erst durch das Betriebssystem umgesetzt. Das hat zum Beispiel den Effekt, dass mit einer deutschen Tastatur an einem auf Englisch eingestellten PC u. a. Y und Z vertauscht sind (und man beim Raspberrz Pi das Passwort mindestens einmal falsch eingibt). Diese Eigenschaft betrifft natürlich auch den Fußtaster. Die Keycodes für englische Tastaturen können in der Spezifikation [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 "Universal Serial Bus HID Usage Tables"] in der aktuellen Version ab Seite 53 (Kapitel 10 Keyboard/Keypad Page (0x07)]) nachgeschlagen werden. Für das deutsche Layout befindet sich eine Tabelle im Download-Bereich (keine Garantie auf Vollständigkeit und Korrektheit). ==Modus 0: Generisches HID== Die Kommunikation findet über Report ID 0 mit 8 Datenbytes statt. Beim Senden von Reports definiert das erste Byte den Befehl, in den weiteren befinden sich die Parameter dessen: {| class="wikitable" ! Nummer || Befehl || Beschreibung |- | 0 || NOP || Keine Operation, dieser Code wird bei den Antworten für den Status des Tasters verwendet |- | 1 || Restart || Neustart des Mikrocontrollers (ersetzt das Aus- und Einstecken nachdem der Modus umgestellt wurde) |- | 2 || Lesen Modus || Gibt den Interface-Modus zurück |- | 3 || Setzen Modus || Setzt den Interface-Modus |- | 4 || Lesen Einzeltaste || Gibt den Keycode der Einzeltasten-Tastatur zurück |- | 5 || Setzen Einzeltaste || Setzt den Keycode der Einzeltasten-Tastatur |- | 6 || Lesen Tastensequenz || Gibt 6 Byte der Sequenz des angegebenen Blocks (in Byte 1) zurück |- | 7 || Setzen Tastensequenz || Setzt die 6 Bytes der Sequenz des angegebenen Blocks (in Byte 1) |} Jeder Befehl wird beantwortet, wobei dem ersten Byte eine Statusinformation mit bitweise Oder hinzugefügt wird: {| class="wikitable" ! Nummer || Status || Beschreibung |- | 0x00 || None || Wird nicht verwendet |- | 0x40 || Busy || Der Befehl wurde nicht ausgeführt, weil der Controller beschäftigt ist |- | 0x80 || Ok || Der Befehl wurde erfolgreich ausgeführt, die optionale Antwort befindet sich in den restlichen Bytes |- | 0xC0 || Error || Beim Ausführen des Befehls ist ein Fehler aufgetreten |} ===Tastenstatus=== Für jede Änderung des Tastenstatus wird ein Report übertragen: <code>&lt; <span class="hb1">00</span> <span class="hb2">BB</span> xx xx xx xx xx xx</code> * <span class="hb1">"Befehl": Status der Taste</span> * <span class="hb2">Status der Taste - 0: nicht gedrückt, 1: gedrückt</span> ==Modus 1: Einzeltasten-Tastatur== In diesem Modus verhält sich der Fußtaster wie die Taste einer Tastatur. Die zu drückende Taste kann über Modus 2 festgelegt werden. Leider ist es aktuell noch nicht möglich, Multimedia-Tasten (Wiedergabesteuerung, Lautstärke, Anwendungssteuerung) zu verwenden. ===Lesen=== Zum Zurücklesen der verwendeten Taste muss folgender Report gesendet werden: <code>&gt; <span class="hb1">04</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste</span> Die Antwort entspricht folgendem Muster: <code>&lt; <span class="hb1">84</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Einzeltaste (OK)</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) ** 0x01: Steuerung links ** 0x02: Umschalttaste links ** 0x04: Alt links ** 0x08: GUI links (u. a. Windows-Taste) ** 0x10: Steuerung rechts ** 0x20: Umschalttaste rechts ** 0x40: Alt rechts (müsste Alt+Gr sein) ** 0x80: GUI rechts (müsste Kontextmenü sein) * <span class="hb3">Keycode Taste</span> ===Schreiben=== Zum Setzen einer Taste folgender Report gesendet werden: <code>&gt; <span class="hb1">05</span> <span class="hb2">MM</span> <span class="hb3">KK</span> xx xx xx xx xx</code> * <span class="hb1">Befehl: Setzen Einzeltaste</span> * <span class="hb2">Bitmaske Modifier</span> (siehe oben) * <span class="hb3">Keycode Taste</span> Die restlichen Bytes im Report werden ignoriert. Die Bestätigung wird wie unter "Modus 2" beschrieben gesendet. Da keine Readback stattfindet, wird immer mit "OK" geantwortet: <code>&lt; <span class="hb1">85</span> xx xx xx xx xx xx xx</code> ==Modus 2: Makro-Tastatur== Über die Makro-Tastatur können längere Tastenfolgen ausgegeben werden. Für diesen Zweck sind 128 Byte im EEPROM vorgesehen, was einer maximalen Folge von etwa 63 Anschlägen entspricht. Aktuell kann nur eine Taste gleichzeitig gedrückt werden kann - ein Rollover ist dementsprechend nicht möglich. Die Ausgabe erfolgt mit maximaler Geschwindigkeit, also mit etwa 100 Anschlägen pro Sekunde, wobei zwischen gleichlautenden Anschlägen sowie nach dem letzten Zeichen automatisch ein Loslassen der Taste eingefügt wird, was zu einer kleinen Verzögerung führt und damit das Timing verändert Beispiel: Bei der Ausgabe des Wortes <code>Hallo</code> folgende Reports übertragen: * Umschalttaste drücken, Taste "H" drücken * Umschalttaste loslassen, Taste "A" drücken * Taste "L" drücken * Taste "L" loslassen * Taste "L" drücken * Taste "O" drücken * Taste "O" loslassen So dauert die Übertragung des Wortes - bei einem Report-Intervall von 10 ms - etwa 70 ms statt den zunächst anzunehmenden 50 ms. ===Datenformat=== Die Daten werden im Muster <code>Befehl + Daten</code> gespeichert, wobei die Datenlänge dynamisch (aber anhand des Befehls ersichtlich) ist. Dementsprechend sind die Befehle teilweise als Flags aufgebaut, zum besseren Verständnis hier im Binärformat: * <code>0b<b>11111111</b></code>: Ende der Sequenz (entspricht nicht beschriebenen Speicherzellen), keine Daten * <code>0b<b>1</b><span class="hb1">ppppppp</span></code>: Pause in 5 ms-Schritten, p = 0 ... 126, t = (p + 1) * 5 ms, maximal 635 ms, keine Daten * <code>0b<b>0</b><span class="hb2">mm</span><span class="hb3">xx</span>xxx</code>: Verhalten der Modifier ** <code><span class="hb2">0b00</span></code>: Modifier beibehalten, keine Daten ** <code><span class="hb2">0b01</span></code>: Modifier für nachfolgende Taste drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb2">0b10</span></code>: Modifier dauerhaft halten, +1 Byte Daten ** <code><span class="hb2">0b11</span></code>: Modifier loslassen, keine Daten * <code>0b<b>0</b><span class="hb2">xx</span><span class="hb3">kk</span>xxx</code>: Verhalten der Taste ** <code><span class="hb3">0b00</span></code>: Taste beibehalten, keine Daten ** <code><span class="hb3">0b01</span></code>: Taste einmal drücken (anschließend loslassen), +1 Byte Daten ** <code><span class="hb3">0b10</span></code>: Taste dauerhaft halten (bis eine andere Taste gedrückt wird), +1 Byte Daten ** <code><span class="hb3">0b11</span></code>: Taste loslassen, keine Daten Sollen Modifier und Taste mit einem Befehl verändert werden, wird zuerst der Modifier erwartet, dann die Taste: <code>0b0<span class="hb2">10</span><span class="hb3">01</span>000 <span class="hb4">0b00000010</span> <span class="hb5">0b00001011</span></code> <span class="hb2">Drückt und hält</span> die <span class="hb4">linke Umschalttaste</span> und drückt die <span class="hb5">Taste H (0x0B)</span> <span class="hb3">einmal</span>. Beispiel: Es soll die Zeichenfolge <code>Hallo WELT</code> mit anschließendem Zeilenumbruch ausgegeben werden, mit einer Pause von 500 ms nach "Hallo". Die Sequenz sieht nun wie folgt aus (Binär und Hex gemischt, Hex für Keycodes): {| class="wikitable" ! Code || Befehl || Parameter |- | <code>0b0<span class="hb1">01</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x0B</span></code> || <span class="hb1">Modifier einmal drücken</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Linke Umschalttaste</span>, <span class="hb4">Taste H</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x04</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste A</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x12</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste O</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1100011</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Pause mit 99 Zeiteinheiten</span>: t = (99 + 1) * 5 ms = 500 ms |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb3">0x2C</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Leertaste</span> |- | <code>0b0<span class="hb1">11</span><span class="hb2">01</span>000 <span class="hb3">0b00000010</span> <span class="hb4">0x1A</span></code> || <span class="hb1">Modifier drücken und halten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb3">Rechte Umschalttaste</span>, <span class="hb4">Taste W</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x08</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste E</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x0F</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste L</span> |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x17</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Taste T</span> |- | <code>0b0<span class="hb1">10</span><span class="hb2">00</span>000</code> || <span class="hb1">Modifier loslassen</span>, <span class="hb2">Kein Tastendruck</span> || - |- | <code>0b0<span class="hb1">00</span><span class="hb2">01</span>000 <span class="hb4">0x28</span></code> || <span class="hb1">Modifier beibehalten</span>, <span class="hb2">Taste einmal drücken</span> || <span class="hb4">Return-Taste</span> |- | <code>0b<span class="hb1">1</span><span class="hb3">1111111</span></code> || <span class="hb1">Pause oder Ende der Sequenz</span> || <span class="hb3">Ende der der Sequenz</span> |} ===Lesen=== Wie bereits in der Befehlsübersicht erwähnt, erfolgt das Lesen und Schreiben der Sequenzdaten in Blöcken: <code>&gt; <span class="hb1">06</span> <span class="hb2">CC</span> xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Lesen Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> Als Antwort bekommt man dann die Daten des jeweiligen Blocks: <code>&lt; <span class="hb1">86</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Lesen Sequenz (OK)</span> * <span class="hb2">Blocknummer: 0 ... 21 </span> * <span class="hb2">6 Datenbytes des Blocks</span> Ist der letzte Block nicht "füllend", sind die restlichen Bytes zufällig, ebenso kann über das "End of Sequence" hinaus gelesen werden. ===Schreiben=== Das Schreiben von Blöcken ist der Antwort vom Lesen sehr ähnlich: <code>&gt; <span class="hb1">07</span> <span class="hb2">CC</span> <span class="hb3">DD DD DD DD DD DD</span></code> * <span class="hb1">Befehl: Schreiben Sequenz</span> * <span class="hb2">Blocknummer: 0 ... 21 (bei 128 Byte Speicher)</span> * <span class="hb2">6 Datenbytes des Blocks</span> Sobald die Daten geschrieben wurden, antwortet der Mikrocontroller mit: <code>&lt; <span class="hb1">06</span> xx xx xx xx xx xx xx</code> * <span class="hb1">Befehl: Schreiben Sequenz (OK)</span> ==Modus 3: Gamepad== Es ist keine Konfiguration notwendig, das Gamepad meldet sich mit einer Taste und kann in Anwendungen wie gewohnt zugeordnet werden. <gallery> footswitch_gamepad.png|Eigenschaftenseite in Windows </gallery> Leider erkennt weder Firefox 73 noch Chromium 82 das Pad im html5gamepad-Tester. Anzumerken ist, dass wie bei der Einzeltasten-Tastatur Reports nur bei Zustandsänderung der Taste gesendet werden. Bis jetzt konnte ich dadurch keine Einschränkungen feststellen. =PC-Software= Aktuell gibt es eine kleine Python-Lib und ein paar Beispiele dazu. Siehe Downloads. =Anmerkungen= * Die Firmware auf dem Tiny85 zu entwickeln war grauenvoll, da man nur sehr schlecht debuggen kann. Das nächste Mal lieber auf einem Mikrocontroller mit deutlich mehr IOs und Hardware-UART entwickeln und anschließend auf ein kleineres Geschwister portieren * [https://github.com/micronucleus/micronucleus/ micronucleus] ist ein USB-Bootloader basierend auf V-USB, den ich bis jetzt noch nicht verwendet habe, in Zukunft aber sollte * Der Quellcode steht, wie von objective development gefordert, unter GPLv2 =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Download= * [[Datei:Footswitch.zip]] Schaltplan & Layout in EAGLE 7.7.0, Firmware & Sourcen in Atmel Studio 7, Beispielanwendung in Python 3.7 =Weblinks= * [https://www.uwe-sieber.de/usbtreeview.html USB Device Tree Viewer] zeigt sehr detaillierte Infos zu angeschlossenen USB-Geräten an * [http://wireshark.org/ Wireshark] kann auch USB tracen * [https://eleccelerator.com/usbdescreqparser/ USB Descriptor and Request Parser] * [https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53 Universal Serial Bus HID Usage Tables, Seite 53: 10 Keyboard/Keypad Page (0x07)] [[Kategorie:AVR]] [[Kategorie:USB]] [[Kategorie:HID]] [[Kategorie:Kleine Helferlein]] b587e7a9fd82d130d188842d483c17159d2b0b0a Datei:Vbuspi 1.3.zip 6 710 1650 1625 2021-06-08T20:00:01Z Chris 2 Chris lud eine neue Version von [[Datei:Vbuspi 1.3.zip]] hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 1651 1650 2021-06-11T19:58:53Z Chris 2 Chris lud eine neue Version von [[Datei:Vbuspi 1.3.zip]] hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.3 assy sch.png 6 714 1652 1629 2021-06-11T20:00:22Z Chris 2 Chris lud eine neue Version von [[Datei:Vbuspi 1.3 assy sch.png]] hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.3 assy opto sch.png 6 713 1654 1628 2021-06-11T20:10:13Z Chris 2 Chris lud eine neue Version von [[Datei:Vbuspi 1.3 assy opto sch.png]] hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.3 assy direct sch.png 6 712 1655 1627 2021-06-11T20:10:43Z Chris 2 Chris lud eine neue Version von [[Datei:Vbuspi 1.3 assy direct sch.png]] hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder/Adapter Nano 0 705 1658 1616 2021-06-11T20:23:22Z Chris 2 /* Einleitung */ wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Einleitung= Die Hardware für den Empfang geht auch deutlich einfacher als in der Protokollbeschreibung und weiter oben auf der Seite gezeigt. Mit einer geschickten Beschaltung eines Komparators braucht man für die Hysterese genau einen Komparator und keinen einzigen Schmitt-Trigger. Das macht die Schaltung kompakt, billig und einfach aufzubauen. Ich hab einfach mal geschaut, wie klein man es machen kann, das Ergebnis lautet: 13x32,5 mm²: <gallery> resol_nano_0.1_sch.png|Schaltplan resol_nano_0.1_assy_top.png|Bestückungsplan Oberseite resol_nano_0.1_assy_bot.png|Bestückungsplan Unterseite resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> Statt des Optokopplers OK1 und R1 sowie C1 können auch die 0-Ohm-Widerstände R10 und R11 bestückt werden, allerdings fällt dann die galvanische Trennung weg und es kann aufgrund der Vorwärtsspannung der Dioden zu einem GND-Offset kommen. Die Bestückungsoption ist allerdings nur der Vollständigkeit halber vorhanden, generell rate ich dazu, die nicht einmal 60 Cent zu investieren. Die drei Halblöcher dienen zum platzsparenden Fixieren mit M2,5-Schrauben. {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 1 || SV1 || || MA04-1 || |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 1 || R9 || 1k || R0603 || RND 0603 1 1K |- | 2 || C1*, C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1* || 3k3 || R0603 || RND 0603 1 3,3K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |} Zu den mit * markierten Bauteilen erhielt ich von Micha folgenden Hinweis: <pre> Ich musste am Ausgang den C entfernen und den PullUp auf 4.7k erhöhen - sonst hat der Raspi das Low nicht erkannt. </pre> '''Nachtrag vom 10.11.2019:''' Nach erneuten Messungen mit 3,3 V auf der Augangsseite stellte sich heraus, dass die Pegel deutlich besser werden, wenn für '''R1 ein 6,8 kOhm-Widerstand und für C1 ein 680 pF-Kondensator''' eingesetzt wird. Wie von Micha beschrieben, kann C1 auch einfach weggelassen werden. Mit dem Weglassen steigt allerdings die Gefahr von Glitches. Update: Bei aktuelleren (6/2021) Messungen hat sich gezeigt, dass selbst bei 6,8k die Low-Pegel noch recht hoch sind, also besser ab 12k für R1 einsetzen. Oder gleich die Schaltung aus [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] verwenden Ich sollte die untenstehenden [[#Messung|Messungen]] also nochmal mit 3,3 Volt wiederholen. Ebenso möchte ich IC1 durch "TS 5205 CX533" ersetzen, der ein gutes Stück günstiger ist. =Aufbau= Der Aufbau kann nach dem üblichen Vorgehen erfolgen, hier ein paar Hinweise, die es vereinfachen * D3 vor D5 bestücken, da die Pads von D3 sehr klein ausfallen * Die Oberseite kann komplett vor der Unterseite bestückt werden. Die Stiftleiste und Anschlussklemmen sind so gut wie gleich hoch =Messung= Kommt auch das raus, was rauskommen soll? Die Spezifikation gibt ein paar Vorgaben: * Maximale Strombelastbarkeit: 35 mA * Schaltschwellen am Slave: 2,25 V Space, 2,00 V Mark So die Theorie. In der Praxis hat die Schaltung eine Stromaufnahme von etwa 3 mA. Den Rest musste ich an der echten Anlage messen, da in der Bastelecke weder ein Resol-Regler noch ein Protokollsimulator (der in diesem Fall relativ einfach ausfallen könnte) herumsteht. Also das Oszi eingepackt und die Schaltung bei meinen Eltern fliegend angeklemmt. Bei den Schaltschwellen sieht es wie folgt aus: <gallery> resol_nano_0.1_meas_threshold.png|Ch1 hinter R8, Ch2 an ICE4A.1 </gallery> Die Schaltschwelle für die steigende Flanke liegt bei etwa 1,96 V, die für die fallende bei 2,44 V. In Hinblick auf die Messgenauigkeit des Oszilloskops und Toleranzen der Widerstände ein mehr als zufriedenstellendes Ergebnis. Der Optokoppler bringt leichte und vor allem asymmetrische Verzögerungen mit sich. Gemessen wird hier das Signal vor (Ch1 an OK1.3) und nach (Ch2 an OK1.6) dem Optokoppler. Als Stromversorgung auf der "rechten Seite" wurde eine Powerbank mit 5,1 V Ausgangsspannung verwendet. Als Schwellenwerte wurden jeweils 0,25 * Vcc und 0,75 * Vcc verwendet. <gallery> resol_nano_0.1_meas_rising.png|Verzögerung steigende Flanke resol_nano_0.1_meas_falling.png|verzögerung fallende Flanke </gallery> Bei steigender Flanke hängt der Ausgang 6,12 µs, bei fallender 8,68 µs hinterher. Die Verzögerung selbst ist hier nicht das Problem, sondern der Verzögerungsunterschied, da dieser die UART-Interfaces der Empfänger durcheinanderbringen kann. Bei den verwendeten 9600 Baud entspricht eine Bitzeit ca. 104 µs. Die Verzögerungsdifferenz der Flanken beträgt mit 2,56 µs lediglich 2,5 % einer Bitzeit. Vernachlässigbar. Wichtig ist ebenfalls, dass die Versorgungsspannung stabil bleibt, da sich sonst die Schaltschwellen verschieben und somit Unsinn übertragen wird. Besonders die Tatsache, dass der Optokoppler bei niedriger Busspannung aktiv ist, kann problematisch werden. Das Oszi-Bild mit Probe am 5V-Ausgang des Reglers und DC-Kopplung war so unspektakulär, dass ich gar keine Bildschirmaufnahme gemacht hab. Interessanter ist da die Betrachtung der Versorgung mit AC-Kopplung: <gallery> resol_nano_0.1_noise.png|Überblick resol_nano_0.1_noise_zoom.png|Nahansicht </gallery> Bisschen hohe Spikes, wobei diese auch mit dem Probing selbst zusammenhängen können (2x 20 cm Dupont-Drähte und EZ-Hooks), ansonsten nur knapp 10 mV Ripple. Passt soweit. =Troubleshooting= Nachdem ich schon ein paar Hilferufe erhalten habe, hier ein kleiner Troubleshooting-Guide - dazu am besten die beiden Bilder (oder zumindest das des Layouts) parallel öffnen: <gallery> Resol_nano_0.1_ts_sch.png|Schaltplan mit Messpunkten Resol_nano_0.1_ts_brd.png|Layout mit Messpunkten </gallery> Für die Messungen ist ein einfaches Multimeter und eine 9 V-Batterie ausreichend. Besser ist jedoch ein Labornetzteil. Um eine Ferndiagnose zu vereinfachen, bitte alle gemessenen Spannungen und Ströme notieren # Leiterkarte nochmal genau ansehen, irgendwelche Lötbrücken, wo keine sein sollten? (Ich weiß, sie ist verdammt eng) # Spannungsquelle auf 9 V einstellen, nachmessen und Spannung notieren. Sofern vorhanden sollte die Strombegrenzung auf etwa 20 mA eingestellt werden. # Spannungsquelle über das Multimeter für eine Strommessung an X1 anschließen (die Polarität ist egal) ## Die Schaltung sollte im Ruhezustand nicht mehr als 3 mA aufnehmen. Ist es mehr oder riecht es "warm": sofort abstecken und nochmal alle Lötstellen prüfen und schauen, ob die richtigen Bauteile bestückt wurden ## Mit Pinzette R5 (<code>S3-G1</code>) kurzschließen, der Strom sollte auf etwa 6 mA ansteigen. Wenn ja: die Wahrscheinlichkeit ist groß, dass alles ok ist :) - wenn nein: Weitermachen # Multimeter auf Spannungsmessung umstellen (umstecken nicht vergessen...) # Spannung über D3 (<code>S1-G1</code>) messen, diese sollte um die Durchflussspannung zweiter Dioden (ca. 1,3 V) geringer als die Eingangsspannung sein. Bei 9 V am Eingang sind das etwa 7,7 Volt. Wenn die Spannung deutlich niedriger ist, sind es ggf. die falschen Dioden verbaut. # Spannung über C5 (<code>S2-G1</code>) messen, sollte um die Durchflussspannung dreier Dioden (ca. 1,95 V) geringer sein als die Eingangsspannung. Bei 9 V am Eingang also um die 7 V. Wenn nicht, siehe letzter Punkt. # Ausgangsspannung des Reglers über C3 (Marker vergessen) messen, sollte ziemlich genau 5,0 V sein. Wenn nicht: Regler checken. # Spannung über C4 (<code>S3-G1</code>) messen, dieser sollte etwa der Hälfte der Sapnnung über D3 entsprechen. Ist der Wert grob daneben, die Widerstände R5 und R8 kontrollieren (2:1-Spannungsteiler) und prüfen, ob der Komparator (IC4) richtig eingelötet ist. # Spannung über R4 (<code>S4-G1</code>) messen, diese sollte ca. 2,03 V betragen. Wenn nicht, R2, R3 und R4 sowie IC4 prüfen. # Spannung über R7 (<code>S5-G1</code>) messen. Diese sollte ca. 1,79 V betragen. Wenn nicht: R6 und R7 sowie IC4 prüfen. # Nun können zusätzlich an SV1.1 3,3 V (oder 5V) und an SV1.4 GND angelegt werden (z. B. vom Raspberry Pi). ## Im Ruhezustand sollte über C1 (<code>S6-G2</code>) 3,3 V anliegen, wenn nicht: R1 prüfen, C1 probehalber entfernen. ## Wird R5 (<code>S3-G1</code>) kurzgeschlossen, sollte die Spannung über über C1 (<code>S6-G2</code>) auf "nahe 0 V" abfallen. Wenn sie nur leicht abfällt, R1 prüfen oder OK1 prüfen/tauschen. Sollte die Schaltung dennoch nicht funktionieren, bitte die notierten Spannungen sowie aussagekräftige Fotos (gut ausgeleuchtet, scharf, zugeschnitten) per E-Mail an mich senden. =Leiterkarten= Es gibt wieder Leiterkarten. Wer eine haben möchte, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbus_nano.zip]] EAGLE-Dateien und LTspice-Simulationsdaten für den VBus-Nano [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] d5ffaff22485b5cb3fb4a2089b992a8436024fb6 Datei:Vbus volkszaehler.zip 6 716 1660 2021-07-04T20:11:05Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 MCP-USB-Bridge 0 514 1665 1410 2021-07-12T19:56:21Z Chris 2 /* Downloads */ Github-Link wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-I²C-Bridge v1.1= Reichelt hat den 23B-500 aus dem Programm genommen. Wer ihn bestellen will, fällt wahrscheinlich auf den 23B-500K herein, der leider 3 Zehnerpotenzen daneben liegt. Das und die relativ schlecht einstellbare IO-Spannung (Bereich und Präzision) hat mich dazu bewogen, das Design abzuwandeln. Neben einem neuen Regler (der leider etwas weniger Strom kann) und Präzisionstrimmer gibt es nun zwei Montagelöcher. Letztere haben leider eine relativ schlechte Clearance zu den Bauteilen. Arg viel besser geht es in diesem Formfaktor leider nicht... Als weiteres Goodie sind jetzt auch die GPIOs (wenn auch sehr klein) beschriftet: <gallery> Mcp2221_usb-i2c_1.1_sch.png|Schaltplan Mcp2221 usb-i2c v1.1 top.png|Bestückungsplan oben Mcp2221 usb-i2c v1.1 bot.png|Bestückungsplan unten Mcp2221 usb-i2c v1.1 assy.jpg|Foto der (größtenteils) aufgebauten Leiterkarte </gallery> Die BOM ist entsprechend fast gleich: {| class="wikitable" ! Menge || Referemz || Wert || Package || Reichelt Bestellcode |- | 1 || JP3 || || JP2Q_NN || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2NN || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C7 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R17 || 200k || S64Y || 64Y-200K |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || C6 || 4u7 10V || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 56k || R0603 || RND 0603 1 56K |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || IC3 || TPS76301 || SOT23-DBV || TPS 76301 DBVR |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Hinsichtlich der BOM gibt es auch ein ziemliches Problem: Reichelt hat die eigentlichen Standardwerte 0603 100 nF, 0603 470 nF, 0805 1 µF/16 V aktuell (02/2020) gar nicht mehr im Programm, die USB-Buchse habe ich bis jetzt noch nie lieferbar gesehen. Auch wenn sich die Probleme einfacher umgehen lassen - was zum ... ist da los? =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. * '''Achtung''': Unter Python >= 3.8 gibt es aktuell wohl keine "wunschlos glücklich" hidapi-Lib. Zumindest bei meinen Versuchen wollte das Teil beim Installieren nicht bauen. Workaround: Python 3.7 verwenden. Deshalb: es wird eine Version 2 geben. Das Datenblatt des MCP2221 enthält ein paar Fehler bzw. fehlen Informationen: * Die Berechnung der I²C-Clock ist eher ungenau * Es fehlen wichtige Informationen zu den Zuständen der Statemachines, die Microchip auch auf Rückfrage nicht herausrücken wollte, für die Implementierung aber zwingend erforderlich sind. Hier musste ich mutmaßen * Im Befehl zum Setzen der SRAM-Settings ist der angegebene Wert zum Schreiben der GPIO-Settings (Byte 7) falsch * Das Umstellen der ADC-Referenz muss nach dem Setzen der Pinfunktion erfolgen, da sonst die Referenz auf den Default-Wert gesetzt werden =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =C#-Lib= Um auch aus C# heraus und nicht (wie mit der Lib von Microchip) an ein .NET-Framework gebunden zu sein, habe ich auch eine Bibliothek sowohl für den MCP2221 als auch MCP2210 in nativem C# (ohne externe DLLs oder sonstige Abhängigkeiten) geschrieben. Einige, für den täglichen Bedarf weniger benötigte, Funktionen wurden ausgelassen; die Performance ist zumindest bei I²C ähnlich gut wie die der Python-Lib. Codebeispiele und entsprechende Anwendungen werden folgen, sobald ich Zeit habe, sie zu vervollständigen. Der unvollständige "Release" ist einfach nur, damit der Code unter die Leute gemischt wird :) Folgende Demos ist aktuell vorbereitet (oder geplant): * MCP2221 ** ADC/(DAC) ** TI INA219 - Current Shunt & Power Monitor ** (TI INA3221 - 3Ch Current Shunt & Power Monitor) ** Microchip MCP4725 - 12-Bit-DAC ** QMC5883L - Magnetometer ** (STM LSM-irgendwas - 6D-Sensor mit Schrittzähler) ** (Atmel/Microchip Maxtouch-Touchcontroller) ** (Avago/Broadcomm APDS-99x0 - Ambient light/Gesten-/Farb-Sensor) * MCP2210 ** Maxim MAX31855 - K-Typ Temperatursensor ** Maxim MAX7219 - LED-Treiber ** Nordic Semi nRF24L01+ - 2,4 GHz Transceiver (+ [https://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/ BLE-Hack], der Logitech-Hack ist aktuell nicht geplant) ** (TI CC1101 - Low-Power Sub-1 GHz RF Transceiver) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Backplate= Im [[3D-Druck-Sammelsurium]] gibt es Backplates zum Selberdrucken =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= * <s>[[Datei:mcp22xx_py.zip]] Python3-Lib v0.2, aktuell nur für MCP2221, mit Beispielen</s> * [https://github.com/chris-heo/mcp22xx_py] Python 3-Lib v0.3 für MCP2221 und MCP2210, mit Beispielen * [[Datei:Mcp22xx cs.zip]] C#-Lib v0.1, für MCP2221 und MCP2210, aktuell noch ohne Beispiele und teilweise ungetestet * [[Datei:MCP-USB-Bridge.zip]] enthält: ** Designdaten beider Boards (jeweils Version 1.0) im EAGLE-Format * [[Datei:mcp-usb-i2c_v1.1.zip]] enthält Version 1.1 des USB-I²C-Adapters im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] b38d5b37bc40785be8e2a2cb61a8895bcc855a49 1666 1665 2021-07-12T19:57:01Z Chris 2 /* Downloads */ wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-I²C-Bridge v1.1= Reichelt hat den 23B-500 aus dem Programm genommen. Wer ihn bestellen will, fällt wahrscheinlich auf den 23B-500K herein, der leider 3 Zehnerpotenzen daneben liegt. Das und die relativ schlecht einstellbare IO-Spannung (Bereich und Präzision) hat mich dazu bewogen, das Design abzuwandeln. Neben einem neuen Regler (der leider etwas weniger Strom kann) und Präzisionstrimmer gibt es nun zwei Montagelöcher. Letztere haben leider eine relativ schlechte Clearance zu den Bauteilen. Arg viel besser geht es in diesem Formfaktor leider nicht... Als weiteres Goodie sind jetzt auch die GPIOs (wenn auch sehr klein) beschriftet: <gallery> Mcp2221_usb-i2c_1.1_sch.png|Schaltplan Mcp2221 usb-i2c v1.1 top.png|Bestückungsplan oben Mcp2221 usb-i2c v1.1 bot.png|Bestückungsplan unten Mcp2221 usb-i2c v1.1 assy.jpg|Foto der (größtenteils) aufgebauten Leiterkarte </gallery> Die BOM ist entsprechend fast gleich: {| class="wikitable" ! Menge || Referemz || Wert || Package || Reichelt Bestellcode |- | 1 || JP3 || || JP2Q_NN || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2NN || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C7 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R17 || 200k || S64Y || 64Y-200K |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || C6 || 4u7 10V || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 56k || R0603 || RND 0603 1 56K |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || IC3 || TPS76301 || SOT23-DBV || TPS 76301 DBVR |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Hinsichtlich der BOM gibt es auch ein ziemliches Problem: Reichelt hat die eigentlichen Standardwerte 0603 100 nF, 0603 470 nF, 0805 1 µF/16 V aktuell (02/2020) gar nicht mehr im Programm, die USB-Buchse habe ich bis jetzt noch nie lieferbar gesehen. Auch wenn sich die Probleme einfacher umgehen lassen - was zum ... ist da los? =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. * '''Achtung''': Unter Python >= 3.8 gibt es aktuell wohl keine "wunschlos glücklich" hidapi-Lib. Zumindest bei meinen Versuchen wollte das Teil beim Installieren nicht bauen. Workaround: Python 3.7 verwenden. Deshalb: es wird eine Version 2 geben. Das Datenblatt des MCP2221 enthält ein paar Fehler bzw. fehlen Informationen: * Die Berechnung der I²C-Clock ist eher ungenau * Es fehlen wichtige Informationen zu den Zuständen der Statemachines, die Microchip auch auf Rückfrage nicht herausrücken wollte, für die Implementierung aber zwingend erforderlich sind. Hier musste ich mutmaßen * Im Befehl zum Setzen der SRAM-Settings ist der angegebene Wert zum Schreiben der GPIO-Settings (Byte 7) falsch * Das Umstellen der ADC-Referenz muss nach dem Setzen der Pinfunktion erfolgen, da sonst die Referenz auf den Default-Wert gesetzt werden =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =C#-Lib= Um auch aus C# heraus und nicht (wie mit der Lib von Microchip) an ein .NET-Framework gebunden zu sein, habe ich auch eine Bibliothek sowohl für den MCP2221 als auch MCP2210 in nativem C# (ohne externe DLLs oder sonstige Abhängigkeiten) geschrieben. Einige, für den täglichen Bedarf weniger benötigte, Funktionen wurden ausgelassen; die Performance ist zumindest bei I²C ähnlich gut wie die der Python-Lib. Codebeispiele und entsprechende Anwendungen werden folgen, sobald ich Zeit habe, sie zu vervollständigen. Der unvollständige "Release" ist einfach nur, damit der Code unter die Leute gemischt wird :) Folgende Demos ist aktuell vorbereitet (oder geplant): * MCP2221 ** ADC/(DAC) ** TI INA219 - Current Shunt & Power Monitor ** (TI INA3221 - 3Ch Current Shunt & Power Monitor) ** Microchip MCP4725 - 12-Bit-DAC ** QMC5883L - Magnetometer ** (STM LSM-irgendwas - 6D-Sensor mit Schrittzähler) ** (Atmel/Microchip Maxtouch-Touchcontroller) ** (Avago/Broadcomm APDS-99x0 - Ambient light/Gesten-/Farb-Sensor) * MCP2210 ** Maxim MAX31855 - K-Typ Temperatursensor ** Maxim MAX7219 - LED-Treiber ** Nordic Semi nRF24L01+ - 2,4 GHz Transceiver (+ [https://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/ BLE-Hack], der Logitech-Hack ist aktuell nicht geplant) ** (TI CC1101 - Low-Power Sub-1 GHz RF Transceiver) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Backplate= Im [[3D-Druck-Sammelsurium]] gibt es Backplates zum Selberdrucken =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= * <s>[[Datei:mcp22xx_py.zip]] Python3-Lib v0.2, aktuell nur für MCP2221, mit Beispielen</s> * [https://github.com/chris-heo/mcp22xx_py|Git-Repo der Python 3-Lib] v0.3 für MCP2221 und MCP2210, mit Beispielen * [[Datei:Mcp22xx cs.zip]] C#-Lib v0.1, für MCP2221 und MCP2210, aktuell noch ohne Beispiele und teilweise ungetestet * [[Datei:MCP-USB-Bridge.zip]] enthält: ** Designdaten beider Boards (jeweils Version 1.0) im EAGLE-Format * [[Datei:mcp-usb-i2c_v1.1.zip]] enthält Version 1.1 des USB-I²C-Adapters im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] 0e4c2cca6210aeea12160133cf805c2be2e4fec5 1667 1666 2021-07-12T19:57:22Z Chris 2 /* Downloads */ man sollte halt wikitext können wikitext text/x-wiki "Mal kurz etwas mit I²C/SPI testen". Was einfach klingt artet gerne in vielen Programmierläufen eines Mikrocontrollers aus. Mittlerweile haben die meisten Bastler einen Single Board Computer wie den Raspberry Pi herumliegen, in manchen Situationen wäre eine direkte Anbindung an den PC dann doch angenehmer. Selbst hierfür gibt es Lösungen wie den Aardvark von Total Phase oder den Bus Pirate von Dangerous Prototypes, diese sind entweder vergleichsweise teuer oder umständlich in der Bedienung/Automatisierung. Microchip hat den [https://www.microchip.com/wwwproducts/en/MCP2221 MCP2221] (I²C) und [https://www.microchip.com/wwwproducts/en/MCP2210 MCP2210] (SPI) im Angebot. Dabei handelt es sich [http://www.eevblog.com/forum/reviews/alternatives-to-ftdi-usb-to-uart-converter/msg540581/#msg540581 mutmaßlich um vorprogrammierte Mikrocontroller], was ansich nicht verwerflich ist. Allerdings gibt es ein paar Ecken und Kanten, wie [http://blog.zakkemble.co.uk/mcp2221-hid-library/ Zak] bereits geschrieben und ich [https://hobbyelektronik.org/b/2015/09/mcp2221/ bestätigt] habe. Auch beim MCP2210 hat die im Datenblatt angegebene Datenrate nicht sehr viel mit dem tatsächlichen Durchsatz zu tun. Um etwas zu testen sind jedoch beide Chips ok. Vom Microchip gibt es zwar jeweils auch ein Breakout-Board, beide sind für normalsterbliche jedoch relativ schlecht verfügbar. Deshalb: EAGLE an und los geht's: =USB-I²C-Bridge= Im Prinzip ist die Beschaltung einfach: USB rein, I²C (sowie UART, ein paar GPIOs, ADC und DAC) raus. Da viele I²C-Bausteine mittlerweile nicht mehr mit den früher üblichen 5 Volt funktionieren, gibt es zusätzlich einen Spannungsregler und Levelshifter die, wie im Artikel über den [[Lichtsensor_Avago_APDS-9300#Levelshifter|APDS-9300]], der [http://www.nxp.com/documents/application_note/AN10441.pdf AN10441 von NXP] folgen. Der ADC an GP3 kann zugleich für die Spannungsmessung des Reglers verwendet werden, um bei Änderungen der IO-Spannung nicht unbedingt ein Messgerät anschließen muss. Damit die interne Messung funktioniert, müssen beide Jumper gesteckt und damit die Versorgung der "VIO"-Pins aktiviert werden. Mit bisschen Gewalt bekommt man einen Jumper vertikal gesteckt und kann ohne aktivertem VIO messen... Auch ein Punkt für Revision 2. <gallery> mcp2221_usb-i2c_sch.png | Schaltplan der USB-I²C-Bridge mcp2221_usb-i2c_brd_top.png | Layout oben mcp2221_usb-i2c_brd_bot.png | Layout unten mcp2221_usb-i2c_assy_top.png | Bestückungsplan oben mcp2221_usb-i2c_assy_bot.png | Bestückungsplan unten mcp2221_usb-i2c_photo.jpg | Foto der (teil-)aufgebauten Leiterkarte </gallery> Der verwendete LM317 hat leider einen Nachteil: da seine Feedback-Spannung gegen Vout referenziert wird, kommt er nicht sehr nahe an die Eingangsspannung heran. Praktisch kommen maximal knapp 3,3 V am Ausgang an. Reicht für die meisten Anwendungen, für manche Bauelemente ist es allerdings zu wenig. Beim nächsten Mal kommt ein anderer Regler, versprochen. Die BOM ist überschaubar: {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || JP1, JP2 || || JP1 || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2 || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C6 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R18 || 23B-500 || POT-23B || 23B-500 |- | 1 || R9 || 240 || R0603 || RND 0603 1 240 |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC2 || LM317LD || SO08 || LM 317 LD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Um kurz etwas zu testen bietet sich die Software "MCP2221 I2C SMBus Terminal", die man auf der Produktseite von Mikrochip herunterladen kann. Die C#-Implementierung von Microchip ist leider nicht die schönste, eine echte Alternative habe ich leider noch nicht gefunden (vielleicht kommt hier etwas). =USB-I²C-Bridge v1.1= Reichelt hat den 23B-500 aus dem Programm genommen. Wer ihn bestellen will, fällt wahrscheinlich auf den 23B-500K herein, der leider 3 Zehnerpotenzen daneben liegt. Das und die relativ schlecht einstellbare IO-Spannung (Bereich und Präzision) hat mich dazu bewogen, das Design abzuwandeln. Neben einem neuen Regler (der leider etwas weniger Strom kann) und Präzisionstrimmer gibt es nun zwei Montagelöcher. Letztere haben leider eine relativ schlechte Clearance zu den Bauteilen. Arg viel besser geht es in diesem Formfaktor leider nicht... Als weiteres Goodie sind jetzt auch die GPIOs (wenn auch sehr klein) beschriftet: <gallery> Mcp2221_usb-i2c_1.1_sch.png|Schaltplan Mcp2221 usb-i2c v1.1 top.png|Bestückungsplan oben Mcp2221 usb-i2c v1.1 bot.png|Bestückungsplan unten Mcp2221 usb-i2c v1.1 assy.jpg|Foto der (größtenteils) aufgebauten Leiterkarte </gallery> Die BOM ist entsprechend fast gleich: {| class="wikitable" ! Menge || Referemz || Wert || Package || Reichelt Bestellcode |- | 1 || JP3 || || JP2Q_NN || |- | 2 || LED1, LED2 || || CHIP-LED0603 || LED EL 0603 GR1 |- | 5 || SV1, SV3, SV4, SV5, SV8 || || MA04-2NN || |- | 1 || R2 || 0 || R0603 || RND 0603 0 |- | 1 || R10 || 100 || R0603 || RND 0603 1 100 |- | 3 || C3, C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R1 || 10k || R0603 || RND 0603 1 10K |- | 1 || C2 || 10n || C0603 || KEM X7R0603 10N |- | 1 || C7 || 1u || C0805 || X7R-G0805 1,0/16 |- | 1 || R17 || 200k || S64Y || 64Y-200K |- | 1 || R7 || 22k || R0603 || RND 0603 1 22k |- | 1 || R15 || 2k2 || R0603 || RND 0603 1 2,2k |- | 9 || R3, R4, R5, R6, R8, R11, R12, R13, R14 || 3k3 || R0603 || RND 0603 1 3,3k |- | 1 || C1 || 470n || C0603 || NPO 0603 CD 470N |- | 1 || C6 || 4u7 10V || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 56k || R0603 || RND 0603 1 56K |- | 1 || R16 || 680 || R0603 || RND 0603 1 680 |- | 4 || Q1, Q2, Q3, Q4 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC1 || MCP2221-I/SL || SO-14 || MCP2221-I/SL |- | 1 || IC3 || TPS76301 || SOT23-DBV || TPS 76301 DBVR |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA_HANDSOLDER || MIC USB BBU |} Hinsichtlich der BOM gibt es auch ein ziemliches Problem: Reichelt hat die eigentlichen Standardwerte 0603 100 nF, 0603 470 nF, 0805 1 µF/16 V aktuell (02/2020) gar nicht mehr im Programm, die USB-Buchse habe ich bis jetzt noch nie lieferbar gesehen. Auch wenn sich die Probleme einfacher umgehen lassen - was zum ... ist da los? =USB-SPI-Bridge= Der MCP2210 unterstützt von sich aus 2 IO-Spannungen: 5 V und 3,3 V. Ausreichend für die meisten SPI-Bausteine. Einen Levelshifter für weitere Spannungen wollte ich auf dem Board aus Platzgründen nicht integrieren. Der 3,3 V-Regler kann lt. Datenblatt mit 250 mA vergleichsweise viel Strom. Bedenkt man, dass bei einer Versorgungsspannung von 5 V (tendenziell mehr) und dieser Stromstärke 425 mW verbraten werden müssen - eher nein. Dauerhaft 100 mA sollten allerdings kein größeres Problem sein. Da mein Hauptverwendungszweck das Ansteuern von Funkmodulen sein wird, sind Buchsenleisten für die weit verbreiteten nRF24L01+- und CC1101-Module vorhanden. Ferner sind alle IOs herausgeführt, beschriftet und mit 100 Ohm im Strom begrenzt: Auch hier ist die BOM überschaubar: {| class="wikitable" ! Menge || Parts || Wert || Package || Reichelt Bestellcode |- | 1 || JP1 || || JP3Q || |- | 1 || LED1 || || SML0603 || LED EL 0603 GR1 |- | 2 || SV1, SV2 || || MA08-1 || |- | 1 || R1 || 0 || R0603 || RND 0603 0 |- | 12 || R4, R5, R6, R7, R8, R10, R11, R12, R13, R14, R15, R16 || 100 || R0603 || RND 0603 1 100 |- | 2 || C4, C5 || 100n || C0603 || KEM X7R0603 100N |- | 1 || R3 || 10k || R0603 || RND 0603 1 10k |- | 2 || C1, C2 || 10p || C0603 || NPO-G0603 10P |- | 1 || Q1 || 12M || MJ || 12,000000-MJ |- | 1 || R2 || 1k || R0603 || RND 0603 1 1k |- | 2 || C6, C7 || 1u || C0805 || KEM X5R0805 1,0U |- | 1 || C3 || 330n || C0603 || KEM X7R0603 330N |- | 2 || X2, X3 || FE04-2 || FE04-2 || |- | 1 || IC2 || MCP1700T-3302E/TT || SOT23 || MCP 1700-3302 |- | 1 || IC1 || MCP2210/SO || SO20L || MCP 2210I-SO |- | 1 || X1 || ZX62-B-5PAHS || ZX62-B-5PA || MIC USB BBU |} <gallery> mcp2210_usb-spi_sch.png | Schaltplan der USB-SPI-Bridge mcp2210_usb-spi_brd_top.png | Layout oben mcp2210_usb-spi_brd_bot.png | Layout unten mcp2210_usb-spi_assy_top.png | Bestückungsplan oben mcp2210_usb-spi_assy_bot.png | Bestückungsplan unten mcp2210_usb-spi_photo.jpg | Foto der aufgebauten Leiterkarte mcp2210_usb-spi_cc1101_photo.jpg | Leiterkarte mit aufgestecktem CC1101-Modul mcp2210_usb-spi_nrf24l01_photo.jpg | Leiterkarte mit aufgestecktem nRF24L01+-Modul </gallery> Auch hier gilt: die Implementierung von Microchip ist nicht die Beste. Eine richtige Alternative für C# und Python habe ich hier auch noch nicht gefunden. =Anmerkungen= * Der zusätzliche "Bestückungsdruck" für die Pinbezeichnungen befindet sich im Layer tSilk in Lage 100. Wenn Produktionsdaten ausgegeben werden, diese bitte nicht vergessen. Ist mir bei der SPI-Bridge passiert, weshalb dort ein Stück Papier als Ersatz. * Der Spannungsteiler für die VIO-Messung an der I2C-Bridge ist ungünstig verschaltet. Dadurch können speziell hochohmige Signale bei ADC-Messungen nach unten "verzogen" werden. * Die Spannungsmessung von VIO sollte auch möglich sein, wenn der Enable-Jumper nicht gesetzt ist * Wie bereits erwähnt, ist der Bereich für VIO bei der I2C-Bridge etwas klein. * '''Achtung''': Unter Python >= 3.8 gibt es aktuell wohl keine "wunschlos glücklich" hidapi-Lib. Zumindest bei meinen Versuchen wollte das Teil beim Installieren nicht bauen. Workaround: Python 3.7 verwenden. Deshalb: es wird eine Version 2 geben. Das Datenblatt des MCP2221 enthält ein paar Fehler bzw. fehlen Informationen: * Die Berechnung der I²C-Clock ist eher ungenau * Es fehlen wichtige Informationen zu den Zuständen der Statemachines, die Microchip auch auf Rückfrage nicht herausrücken wollte, für die Implementierung aber zwingend erforderlich sind. Hier musste ich mutmaßen * Im Befehl zum Setzen der SRAM-Settings ist der angegebene Wert zum Schreiben der GPIO-Settings (Byte 7) falsch * Das Umstellen der ADC-Referenz muss nach dem Setzen der Pinfunktion erfolgen, da sonst die Referenz auf den Default-Wert gesetzt werden =Python-Lib= ==MCP2221== Nachdem ich keine Python-Bibliothek finden konnte, die zumindest größere Datentransfers (> 60 Byte) erlaubt, habe ich angefangen, selbst eine zu schreiben. Sie umfasst aktuell folgende Features des MCP2221: {| class="wikitable" ! Funktion || Status || Anmerkung |- | I²C Read/Write || getestet || bis 65535 Byte |- | DAC || getestet || |- | ADC || getestet || |- | GPIO || ungetestet || |- | Interrupt || nicht implementiert || |- | Flash-Settings || nicht implementiert || aktuell nicht geplant |- |} Während der Implementierung stellte sich heraus, dass das Datenblatt an ein paar Stellen Fehler hat und auch an relevanten Stellen unvollständig ist. Z. B. ist für eine saubere Implementierung das Wissen über die Status der I²C-Engine nötig. Laut Datenblatt ist diese Information "internal". Im Linux-Treiber kann man einige dieser Werte herausziehen. Auf Anfrage teilte mir der verantwortliche Entwickler mit, dass diese Information nicht herausgegeben wird. Insgesamt scheint die Implementierung im Controller nicht vollständig sauber zu sein, folgendes ist mir aufgefallen: * Ungültige Anfragen (z. B. falsche Werte bei cancel current I²C transfer) werden mit "success" beantwortet * I2C_Cancel nach einem Reset des Chips führt zu einem Deadlock (kein Workaround) * Wird direkt nach einem Enumerate das Device geöffnet, geht der Chip ebenfalls in einen Deadlock. Kann aber auch an der HID-Lib oder an meinem PC liegen (Workaround: warten bevor das device geöffnet wird, ist implementiert) Ferner ist anzumerken, dass die Lib noch keinen Stable-Zustand verdient. Dafür ist sie einfach zu wenig und zu einseitig getestet. ===Performance=== Obwohl der Chip I²C-Taktraten bis 400 kHz (und noch ein bisschen mehr) unterstützt, den damit verbundenen Datendurchsatz erreicht man leider beiweitem nicht. Das hängt zum einen mit der Verwendung des USB-HID zusammen, zum anderen scheint das I²C-Interface oder die Implementierung auf dem Controller nicht hinreichend optimiert zu sein. Für die Messung wurden 2400 Byte schreibend bzw. lesend übertragen. Die Datenlänge entspricht dem Vielfachen der verwendeten Blockgröße von 60 Byte. Die verwendeten Scripts befinden sich im Beispielordner der Lib. Die Messung wurde mehrfach wiederholt, jedoch fließen in die Tabelle und die Diagramme die Samplegröße 1 ein. Der MCP2221 wurde an einen USB-Port ohne weitere Devices angeschlossen. {| class="wikitable" ! SCL freq [kHz] || write execution time [ms] || write throughput [kbit/s] || write efficiency [%] || read execution time [ms] || read throughput [kbit/s] || read efficiency [%] |- | 50,1 || 547 || 39,5 || 78,84 || 639 || 33,81 || 67,5 |- | 100,4 || 313 || 69,03 || 68,75 || 479 || 45,11 || 44,9 |- | 150,9 || 235 || 91,95 || 60,92 || 320 || 67,52 || 44,7 |- | 201,7 || 235 || 91,95 || 45,59 || 320 || 67,52 || 33,5 |- | 252,6 || 157 || 137,63 || 54,48 || 240 || 90,03 || 35,6 |- | 303,8 || 158 || 136,76 || 45,02 || 240 || 90,03 || 29,6 |- | 347,8 || 158 || 136,76 || 39,32 || 240 || 90,03 || 25,9 |- | 406,8 || 158 || 136,76 || 33,62 || 240 || 90,03 || 22,1 |- | 452,8 || 158 || 136,76 || 30,2 || 240 || 90,03 || 19,9 |} <gallery> mcp2211_usb-i2c_throughput.png|Datendurchsatz über Bitrate mcp2211_usb-i2c_efficiency.png|Übertragungseffizienz über Bitrate </gallery> Der sweet spot liegt also bei ungefähr 250 kHz, trotzdem werden dabei lediglich knapp 140 kbit/s erreicht. Nicht wirklich berauschend. Trotzdem bleibt das Argument: eine günstige (oder in dem Fall billige?) Lösung. =C#-Lib= Um auch aus C# heraus und nicht (wie mit der Lib von Microchip) an ein .NET-Framework gebunden zu sein, habe ich auch eine Bibliothek sowohl für den MCP2221 als auch MCP2210 in nativem C# (ohne externe DLLs oder sonstige Abhängigkeiten) geschrieben. Einige, für den täglichen Bedarf weniger benötigte, Funktionen wurden ausgelassen; die Performance ist zumindest bei I²C ähnlich gut wie die der Python-Lib. Codebeispiele und entsprechende Anwendungen werden folgen, sobald ich Zeit habe, sie zu vervollständigen. Der unvollständige "Release" ist einfach nur, damit der Code unter die Leute gemischt wird :) Folgende Demos ist aktuell vorbereitet (oder geplant): * MCP2221 ** ADC/(DAC) ** TI INA219 - Current Shunt & Power Monitor ** (TI INA3221 - 3Ch Current Shunt & Power Monitor) ** Microchip MCP4725 - 12-Bit-DAC ** QMC5883L - Magnetometer ** (STM LSM-irgendwas - 6D-Sensor mit Schrittzähler) ** (Atmel/Microchip Maxtouch-Touchcontroller) ** (Avago/Broadcomm APDS-99x0 - Ambient light/Gesten-/Farb-Sensor) * MCP2210 ** Maxim MAX31855 - K-Typ Temperatursensor ** Maxim MAX7219 - LED-Treiber ** Nordic Semi nRF24L01+ - 2,4 GHz Transceiver (+ [https://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/ BLE-Hack], der Logitech-Hack ist aktuell nicht geplant) ** (TI CC1101 - Low-Power Sub-1 GHz RF Transceiver) =Leiterkarten= Es gibt noch unbestückte Leiterkarten. Wer eine will, kann sich gerne bei mir melden. =Backplate= Im [[3D-Druck-Sammelsurium]] gibt es Backplates zum Selberdrucken =Blogposts= <WPPtags tags="MCP2221,MCP2210" /> =Downloads= * <s>[[Datei:mcp22xx_py.zip]] Python3-Lib v0.2, aktuell nur für MCP2221, mit Beispielen</s> * [https://github.com/chris-heo/mcp22xx_py Git-Repo der Python 3-Lib] v0.3 für MCP2221 und MCP2210, mit Beispielen * [[Datei:Mcp22xx cs.zip]] C#-Lib v0.1, für MCP2221 und MCP2210, aktuell noch ohne Beispiele und teilweise ungetestet * [[Datei:MCP-USB-Bridge.zip]] enthält: ** Designdaten beider Boards (jeweils Version 1.0) im EAGLE-Format * [[Datei:mcp-usb-i2c_v1.1.zip]] enthält Version 1.1 des USB-I²C-Adapters im EAGLE-Format [[Kategorie:USB]] [[Kategorie:SPI]] [[Kategorie:I²C]] [[Kategorie:Kleine Helferlein]] [[Kategorie:PC]] b029136d5a3263e20bc90d521a890260089df7a1 Hauptseite 0 1 1668 1639 2021-07-12T20:01:55Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *12.07.2021 Der Pythoncode der [[MCP-USB-Bridge]] ist auf GitGub umgezogen und spricht nun mit dem MCP2210 (SPI) *26.02.2021 Und noch ein Update für den VBus-Decoder: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]] und [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]], sowie einem einfachen [[VBus-Decoder#Protokoll-Analysator|Protokoll-Analysator]] *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> f5f2306d124e8e35c5647832e12d12a88c615834 1669 1668 2021-07-12T20:11:12Z Chris 2 Typo wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *12.07.2021 Der Pythoncode der [[MCP-USB-Bridge]] ist auf GitHub umgezogen und spricht nun mit dem MCP2210 (SPI) *26.02.2021 Und noch ein Update für den VBus-Decoder: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]] und [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]], sowie einem einfachen [[VBus-Decoder#Protokoll-Analysator|Protokoll-Analysator]] *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> 83b273fe559e1993ea25ddce6faff6b4b299800b MediaWiki:Common.css 8 141 1670 1599 2021-09-06T20:58:04Z Qsysopr 1 css text/css /* <source lang="css"> */ /*-----------------------------------------------------------------------------------------------*/ /* ACHTUNG! Common.css enthält die gemeinsamen Skin-Anpassungen der deutschsprachigen Wikipedia */ /*---------------------------------------------------------------------------------------------*/ /* Common.css ist in drei grundlegende Abschnitte gegliedert: */ /* 1. Editierbare Seiteninhalte */ /* 2. Sonstige Anpassungen (Spezialseiten, u.a.) */ /* 3. Hauptseitenspezifisches */ /* Jede Ergänzung/Änderung muss vorher jeweils für alle Skins auf Tauglichkeit getestet werden, */ /* individuell per User.css! Ist hier erstmal geändert, dauert es dank Cache eine Weile, bis die */ /* Änderungen bei allen Nutzern sichtbar oder, bei Fehlern, korrigiert sind. */ /* +++++ 1. ANPASSUNGEN DER ANZEIGE VON EDITIERBAREN SEITENINHALTEN +++++ */ /* Personennamen in Kapitälchen: class="Person" */ .Person { display: inline; font-variant: small-caps; font-style: normal; } /* [[Wikipedia:Zitate|Zitate]] (siehe [[Vorlage:Zitat]]) */ p.Zitat { font-style: normal; margin-bottom: 0; } p.cite { margin-top: 0; padding-left: 1em; } /* [[Wikipedia:Quellenangaben|Quellenangaben]] nicht kursiv, da sie ggf. verschiedene Bestandteile enthalten */ cite { font-style: normal; } /* Stylesheet-Ergänzung zu Standard-[[Wikipedia:Navigationsleisten|Navigationsleisten]] */ div.BoxenVerschmelzen, div.NavFrame { margin: 1.5em 0 0; padding: 2px; border: 1px solid #aaaaaa; text-align: center; border-collapse: collapse; font-size: 95%; clear: both; } div.BoxenVerschmelzen div.NavFrame, div.NavFrame + div.NavFrame { margin-top: 0; } div.BoxenVerschmelzen div.NavFrame { border-style: none; border-style: hidden; } div.NavFrame + div.NavFrame { border-top-style: none; border-top-style: hidden; } div.NavPic { margin: 0; padding: 2px; float: left; } div.NavFrame div.NavHead { font-weight: bold; font-size: 100%; background-color: #efefef; } div.NavFrame p, div.NavFrame div.NavContent, div.NavFrame div.NavContent p { font-size: 100%; } div.NavEnd { margin: 0; padding: 0; line-height: 1px; clear: both; } /* Stylesheet fuer den 'Ausklappen'-Button an Navileisten, der in [[MediaWiki:Common.js]] implementiert wird */ .NavToggle { font-size: x-small; float: right; } /* Workaround für Internet Explorer 6 */ div.NavFrame, div.NavPic, .NavToggle { position: relative; } /* Stylesheet-Ergänzung zu SideBoxen (ehedem [[Wikipedia:TownBox|TownBox]]) */ div.sideBox { position: relative; float: right; background: white; margin-left: 1em; border: 1px solid gray; padding: 0.3em; width: 200px; overflow: hidden; clear: right; } div.sideBox dl { padding: 0; margin: 0 0 0.3em 0; font-size: 96%; } div.sideBox dl dt { background: none; margin: 0.4em 0 0 0; } div.sideBox dl dd { margin: 0.1em 0 0 1.1em; background-color: #f3f3f3; } /* Stylesheet-Ergänzung zu [[Wikipedia:Taxoboxen|Taxoboxen]] und [[Wikipedia:Paläoboxen|Paläoboxen]] */ table.taxobox, table.palaeobox { border-collapse: collapse; border: 1px solid gray; float: right; clear: right; margin-left: 0.5em; background-color: white; } table.taxobox th { background-color: #9bcd9b; } table.palaeobox th { background-color: #e7dcc3; } table.taxobox th, table.palaeobox th { border: solid 1px gray; text-align: center; font-weight: bold; } table.taxobox td, table.palaeobox td { vertical-align: top; } table.taxobox .Person, table.palaeobox .Person { font-style: normal; } table.taxobox div.thumb, table.taxobox div.thumb * { background-color: #f9f9f9; } table.taxobox div.thumb, table.taxobox div.thumb *, table.palaeobox div.thumb, table.palaeobox div.thumb * { margin: 0 auto; padding: 0; float: none; border: none; } table.taxobox div.magnify, table.palaeobox div.magnify { display: none; } table.taxobox tr td div.thumb div div.thumbcaption { text-align: center; } table.palaeobox tr td div.thumb div div.thumbcaption { text-align: left; } table.taxobox td.Person, table.palaeobox td.Person { text-align: center; display: block; } table.taxobox td.taxo-name, table.taxobox td.taxo-bild, table.palaeobox td.taxo-name, table.palaeobox td.taxo-bild, table.palaeobox td.taxo-zeit { text-align: center; } table.palaeobox td.taxo-ort { text-align: left; } /* aus Vorlage zur Entlastung, skinabhängigen Darstellung und Kombinierbarkeit hierher ausgelagert */ .wikitable, .prettytable { margin: 1em 1em 1em 0; background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse; } .prettytable th, .prettytable td { border: 1px #aaa solid; padding: 0.2em; } .prettytable th { text-align: center; } .prettytable caption { font-weight: bold; } /* Zebra-Tabellen */ table.wikitable.zebra tr:nth-child(even) { background: white; } .nogrid th, .nogrid td { border: none; } div.float-left, table.float-left, .float-left { float: left; clear: left; } div.float-right, table.float-right, .float-right { float: right; clear: right; margin: 1em 0 1em 1em; } div.centered, table.centered, .centered { margin-left: auto; margin-right: auto; } .toptextcells td { vertical-align: top; } /* Bitte KEINE weiteren Definitionen dieser Art für Boxen hier, das gehört in entsprechende Vorlagen! */ /* Hier 20 Mal Trivialitäten wie "text-align:center" zu definieren verlangsamt alles und ist nicht */ /* Sinn der Sache. (Und wer nicht weiß warum, hat's nicht verstanden.) */ /* Do not expand [[Wikipedia:WikiProjekt Georeferenzierung|kvaleberg.com-URLs]] for printing */ #content span.coordinates a.external.text:after, #content span.coordinates a.external.autonumber:after, #content div.coordinates a.external.text:after, #content div.coordinates a.external.autonumber:after { content: ""; } /* Do not expand URLs for printing */ #content span.plainlinks-print a.external.text:after, #content span.plainlinks-print a.external.autonumber:after, #content div.plainlinks-print a.external.text:after, #content div.plainlinks-print a.external.autonumber:after { content: ""; } /* Metadaten (bspw. [[Wikipedia:Personendaten|Personendaten]]) */ table.metadata { border: 1px solid #aaaaaa; display: none; } .metadata-label { color: #aaaaaa; } span.metadata, span.metadata-inline { display: none; } /* * Farbdefinitionen für Rahmen und Hintergründe von [[Wikipedia:Textbausteine|Textbausteinen]]. * Hier: Standardvorgaben für "dunkle Schrift auf hellem Grund". * Für Hell-auf-dunkel-Skins ([[MediaWiki:Amethyst.css|Amethyst]]) müssen dort entsprechende Definitionen * zusätzlich eingetragen werden! Anpassungen für andere Skins sind optional. * (Die Angaben der Rahmenstärke dienen der Bequemlichkeit, so dass man * für dünne Rahmen nur noch "border-style" angeben muss.) */ .rahmenfarbe1 { /* Wie Inhaltsverzeichnis */ border-color: #aaaaaa; border-width: 1px; } .rahmenfarbe2 { /* Unauffällig, geringer Kontrast */ border-color: #e9e9e9; border-width: 1px; } .rahmenfarbe3 { /* "Rot", auffällig */ border-color: #c00000; border-width: 1px; } .rahmenfarbe4 { /* Neutrale Farbe, deutlich */ border-color: #8888aa; border-width: 1px; } .rahmenfarbe5 { /* "Schwarz", hoher Kontrast */ border-color: #000000; border-width: 1px; } tr.hintergrundfarbe1 th, tr th.hintergrundfarbe1, table.hintergrundfarbe1, .hintergrundfarbe1 { /* Wie Inhaltsverzeichnis */ background-color: #f9f9f9; } tr.hintergrundfarbe2 th, tr th.hintergrundfarbe2, table.hintergrundfarbe2, .hintergrundfarbe2 { /* "Weiß", für Nicht-Artikel-Seiten, neutral */ background-color: #ffffff; } tr.hintergrundfarbe3 th, tr th.hintergrundfarbe3, table.hintergrundfarbe3, .hintergrundfarbe3 { /* "Gelb", auffällig */ background-color: #ffff40; } tr.hintergrundfarbe4 th, tr th.hintergrundfarbe4, table.hintergrundfarbe4, .hintergrundfarbe4 { /* Sehr auffällig */ background-color: #ffaa00; } tr.hintergrundfarbe5 th, tr th.hintergrundfarbe5, table.hintergrundfarbe5, .hintergrundfarbe5 { /* Neutral, abgesetzt */ background-color: #e0e0e0; } tr.hintergrundfarbe6 th, tr th.hintergrundfarbe6, table.hintergrundfarbe6, .hintergrundfarbe6 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b3b7ff; } tr.hintergrundfarbe7 th, tr th.hintergrundfarbe7, table.hintergrundfarbe7, .hintergrundfarbe7 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffcbcb; } tr.hintergrundfarbe8 th, tr th.hintergrundfarbe8, table.hintergrundfarbe8, .hintergrundfarbe8 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffebad; } tr.hintergrundfarbe9 th, tr th.hintergrundfarbe9, table.hintergrundfarbe9, .hintergrundfarbe9 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b9ffc5; } /* Keine Vergrößerung der Zeilenhöhe durch hochgestellte Zahlen der Fußnoten */ sup.reference { font-weight: 400; font-style: normal; } sup, sub { line-height: 1em; } /* Hervorhebung der angeklickten Fußnoten und der Rückverweise in blau */ ol.references > li:target, sup.reference:target { background-color: #def; } /* Hochgestellte Buchstaben in der Einzelnachweiseliste kursiv setzen */ ol.references li a[href|="#cite_ref"] { font-style: italic; } /* Inline-Verwendung der [[:Kategorie:Vorlage:Schwesterprojektverweis|Schwesterprojektverweise]] */ ol.references li div.sisterproject { display: inline !important; } /* Für <nowiki><hiero>…</hiero></nowiki> */ .mw-hierotable, .mw-hierotable th, .mw-hierotable td { border: 0; padding: 0; } /* Für [[MediaWiki:Anoneditwarning]] und weitere Hinweise, die alle untereinander stehen */ #mw-anon-edit-warning, #mw-missingsummary, #wp_talkpagetext { width: 80%; background: #d3e1f2; border: 1px solid #1a47ff; margin: 1em auto; padding: 1em; } /* Bei URLs, die auf unser Projekt und verwandte Projekte verweisen, den Pfeil ausblenden * Dieser Pfeil dient nur dazu, auf externe Ziele hinzuweisen * Auf den Einsatz der Klasse "plainlinks" kann dadurch verzichtet werden */ #content a[href^="http://de.wikipedia.org"], #content a[href^="http://toolserver.org"] { background: none !important; padding-right: 0 !important; } #content .mw-search-formheader div.search-types ul li a[href^="http://de.wikipedia.org"], #content .mw-search-formheader div.search-types ul li a[href^="http://toolserver.org"] { padding-right: 0.5em !important; } /* Falls bei der Seitenbearbeitung vergessen wurde, die Zusammenfassung auszufüllen */ .mw-summarymissed { border: 5px solid red; padding: 2px; } /* Copyrightwarnung */ #editpage-copywarn { border: solid 1px #c00000; font-size: 90%; background-color: #ffffff; } .mw-tos-summary { border: solid 1px #c00000; background-color: #ffffff; padding-left: 1em; } /* +++++ 2. SONSTIGE ANPASSUNGEN (Spezialseiten u. a.) +++++ */ /* Markierung von Redirects in [[Special:Allpages]], [[Special:Watchlist]], Kategorien */ .allpagesredirect, .watchlistredir, .redirect-in-category { font-style: italic; } /* Fettformatierung von Admin-Spezialseiten in [[Special:Specialpages]] abschalten */ .mw-specialpagerestricted strong { font-weight: normal; } /* Legende auf [[Special:Specialpages]] ebenfalls abschalten */ div.mw-specialpages-notes { display: none; } /* Größerer Abstand zwischen TOC-Nummerierung und TOC-Eintrag */ span.tocnumber { margin-right: 0.3em; } /* Skinabhängige absolute Positionierungen ausblenden */ /* Bitte [[MediaWiki Diskussion:Common.css#Absolute_Positionierungen]] beachten */ #coordinates, #coordinates_3_ObenRechts, #issnlink, #editcount, #shortcut, #artikelstadium, .topicon, #spoken-icon, #commons-icon { display: none; } /* Anpassungen für [[:Template:Link_FA]] */ /* hide the template */ #bodyContent span.FA { display: none; } /* change the bullets for links to special articles */ #p-lang li.FA { /* hier immer auch linkFA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/d/d0/Monobook-bullet-star-transparent.png"); } /* change the bullets for links to special articles */ #p-lang li.GA { /* hier immer auch linkGA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/a/a1/Monobook-bullet-star-gray.png"); } /* Verhindere, dass Infoboxen etc. in den Inhalt von Kategorien hineinragen. Das betrifft nur Kategorieseiten. */ #mw-subcategories, #mw-pages { clear: both; } /* DIVs in ImageMaps inlinen (Vorschlag von Revolus) */ .imagemap-inline div { display: inline; } /* [[Special:Hochladen]]: Warnmeldung auf bestehende Dateien, unerwünschte Prefixe usw. deutlicher hervorheben. */ #wpDestFile-warning ul { border: solid red 1px; padding: 1.5em; } /* Warnmeldung für gesperrte Titel */ .mw-titleprotectedwarning { background-color: #eee; border: 2px solid red; padding: 1em; } /* Warnmeldung bei der Bearbeitung von Seiten im MediaWiki-Namensraum */ .mw-editinginterface { background-color: #f9f9f9; border-color: #c00000; border-width: 1px; border-style: solid; padding: 2px; } /* Überschrift 5. und 6. Ordnung proportionaler zu Fließtext */ #content h5 { font-size: 108%; /* Original: 116% */ } #content h6 { font-size: 100%; /* Original: 80% = kleiner als Bodytext, unschön */ } #content h6 .editsection { font-size: 120%; font-weight: normal; } /* Anleitung auf Special:Search */ .mw-searchresult { font-size: 84%; margin: 5px; } /* Gestaltung der Edittools-Leiste */ #specialchars { margin-top: 3px; border: solid 1px #aaaaaa; padding: 1px; text-align: left; background-color: white; } /* Legende für Versionsgeschichte */ .mw-history-legend { font-size: 90%; margin-top: 2px; margin-bottom: 2px; border: solid 1px #e9e9e9; padding: 0 5px 5px 5px; background-color: #f9f9f9; clear: both; } /* +++++ 3. NEUE [[Wikipedia:Hauptseite|HAUPTSEITE]] (ab 2006) +++++ */ /* Kategorie verbergen */ /* Überschrift verbergen */ /* Redirhinweis verbergen - ACHTUNG: Je nach Skin muss jetzt der Abstand zum oberen Rand korrigiert werden */ body.page-Wikipedia_Hauptseite #catlinks, body.page-Wikipedia_Hauptseite h1.firstHeading, body.page-Wikipedia_Hauptseite #contentSub { display: none; } #hauptseite h2 { background-color: #d8e8ff; border: 1px solid #8898bf; font-size: 1em; font-weight: bold; margin-top: 0; margin-bottom: 0; padding-top: 0.1em; padding-bottom: 0.1em; } #hauptseite .inhalt { background-color: #ffffff; border: 1px solid #8898bf; border-top: 0 solid white; padding: 0.3em 0.8em 0.4em 0.8em; } #hauptseite .inhalt hr { background-color: #8898bf; color: #8898bf; height: 1px; margin: 0.5em 0; padding: 0; } #hauptseite .inhalt .mehr { clear: both; font-size: 95%; margin-top: 0.8em; text-align: right; } #hauptseite table { background-color: transparent; } .hauptseite-oben, .hauptseite-links, .hauptseite-rechts { margin-bottom: 1em; } .hauptseite-links { margin-right: 0.5em; } .hauptseite-rechts { margin-left: 0.5em; } .hauptseite-oben h2, .hauptseite-unten h2 { text-align: center; } .hauptseite-oben .inhalt .portale { font-weight: bold; margin-top: 0.2em; margin-bottom: 0.2em; } .hauptseite-oben .inhalt .intern { font-size: 90%; text-align: center; } .hauptseite-links h2, .hauptseite-rechts h2 { text-indent: 0.8em; } #hauptseite-schwesterprojekte .inhalt a { font-weight: bold; } /* IPA links nicht unterstreichen */ .IPA a:link, .IPA a:visited { text-decoration: none; } /* CSS-Klassen für Schriftarten als Workaround für Defizite in alten IE-Versionen. * Achtung: IE6 mag keine Zeilenumbrüche zwischen den Fonts. * In IE8 nicht mehr nötig, soll mit den alten Versionen aussterben. Browserweiche: * http://www.dynamicsitesolutions.com/css/filters/star-html/ * http://www.dynamicsitesolutions.com/css/filters/first-child-plus-html/ */ * html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } *:first-child+html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } * html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } *:first-child+html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } * html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } *:first-child+html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } * html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } *:first-child+html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } * html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } *:first-child+html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } * html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } *:first-child+html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } * html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } *:first-child+html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } * html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } *:first-child+html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } * html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } *:first-child+html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } /* Standardmäßige Ausblendung der Flagged-Revisions-Backlog-Sitenotice */ #mw-oldreviewed-notice { display: none; } /* Standardmäßige Ausblendung der Flagged-Revisions-Kommentarbox */ #mw-commentbox { display: none; } /* Abstand zwischen Liste und Inhaltsverzeichnis erhöhen, siehe http://de.wikipedia.org/w/index.php?title=MediaWiki_Diskussion:Common.css&oldid=51639015#Abstand_vor_Inhaltsverzeichnis */ ul + .toc, ol + .toc { margin-top: 0.5em; } /* höheres Uploadfeld */ #wpUploadDescription { height: 20em; } /* Im Projekt WP:GEO benutzt die [[Vorlage:Coordinate]] das «geo-microformat» zur semantischen Auszeichnung des Texts. Der Inhalt dieses [[Tag (Informatik)|Tags]] ist nicht für den Leser bestimmt. */ .geo { display: none; } /* Patrollink ausblenden, da die Eweiterung hier nicht aktiviert ist und deren Optik zu sehr den gesichteten Versionen ähnelt. */ .fr-diff-patrollink, .patrollink { display: none; } /* Rollback-Knopf auf Beobachtungsliste ausblenden, da es dort nur von sehr beschränktem Nutzen ist und zu sehr vielen Reverts aus Versehen führt */ .page-Spezial_Beobachtungsliste .mw-rollback-link { display: none; } /* </source> */ /* Disable Discussion-tab */ #ca-talk { display: none; } /* reset code style */ code { background-color: none !important; border: none !important; border-radius: 0; padding: 0; } pre { white-space: pre; } /* highlighting */ .hb1 { background-color: #C1F5C1; } .hb2 { background-color: #CDC2EF; } .hb3 { background-color: #FFF6C9; } .hb4 { background-color: #FFC9C9; } .hb5 { background-color: #BED8ED; } .hb6 { background-color: #EDBBED; } .hb7 { background-color: #F4FDC7; } .hb8 { background-color: #FFE8C9; } .hf1 { color: #66D766; } .hf2 { color: #7C67C0; } .hf3 { color: #FFE879; } .hf4 { color: #FF7979; } .hf5 { color: #5D90B7; } .hf6 { color: #B857B8; } .hf7 { color: #E2F876; } .hf8 { color: #FFC679; } .he0 { border: 1px solid grey; border-radius: 4px; } .he1 { border: 1px solid #66D766; border-radius: 4px; } .he2 { border: 1px solid #7C67C0; border-radius: 4px; } .he3 { border: 1px solid #FFE879; border-radius: 4px; } .he4 { border: 1px solid #FF7979; border-radius: 4px; } .he5 { border: 1px solid #5D90B7; border-radius: 4px; } .he6 { border: 1px solid #B857B8; border-radius: 4px; } .he7 { border: 1px solid #E2F876; border-radius: 4px; } .he8 { border: 1px solid #FFC679; border-radius: 4px; } code { line-height: 1em; } 0dd8a3826f43ee94105922c8ab9786d3707f45a8 1671 1670 2021-09-06T21:03:03Z Qsysopr 1 css text/css /* <source lang="css"> */ /*-----------------------------------------------------------------------------------------------*/ /* ACHTUNG! Common.css enthält die gemeinsamen Skin-Anpassungen der deutschsprachigen Wikipedia */ /*---------------------------------------------------------------------------------------------*/ /* Common.css ist in drei grundlegende Abschnitte gegliedert: */ /* 1. Editierbare Seiteninhalte */ /* 2. Sonstige Anpassungen (Spezialseiten, u.a.) */ /* 3. Hauptseitenspezifisches */ /* Jede Ergänzung/Änderung muss vorher jeweils für alle Skins auf Tauglichkeit getestet werden, */ /* individuell per User.css! Ist hier erstmal geändert, dauert es dank Cache eine Weile, bis die */ /* Änderungen bei allen Nutzern sichtbar oder, bei Fehlern, korrigiert sind. */ /* +++++ 1. ANPASSUNGEN DER ANZEIGE VON EDITIERBAREN SEITENINHALTEN +++++ */ /* Personennamen in Kapitälchen: class="Person" */ .Person { display: inline; font-variant: small-caps; font-style: normal; } /* [[Wikipedia:Zitate|Zitate]] (siehe [[Vorlage:Zitat]]) */ p.Zitat { font-style: normal; margin-bottom: 0; } p.cite { margin-top: 0; padding-left: 1em; } /* [[Wikipedia:Quellenangaben|Quellenangaben]] nicht kursiv, da sie ggf. verschiedene Bestandteile enthalten */ cite { font-style: normal; } /* Stylesheet-Ergänzung zu Standard-[[Wikipedia:Navigationsleisten|Navigationsleisten]] */ div.BoxenVerschmelzen, div.NavFrame { margin: 1.5em 0 0; padding: 2px; border: 1px solid #aaaaaa; text-align: center; border-collapse: collapse; font-size: 95%; clear: both; } div.BoxenVerschmelzen div.NavFrame, div.NavFrame + div.NavFrame { margin-top: 0; } div.BoxenVerschmelzen div.NavFrame { border-style: none; border-style: hidden; } div.NavFrame + div.NavFrame { border-top-style: none; border-top-style: hidden; } div.NavPic { margin: 0; padding: 2px; float: left; } div.NavFrame div.NavHead { font-weight: bold; font-size: 100%; background-color: #efefef; } div.NavFrame p, div.NavFrame div.NavContent, div.NavFrame div.NavContent p { font-size: 100%; } div.NavEnd { margin: 0; padding: 0; line-height: 1px; clear: both; } /* Stylesheet fuer den 'Ausklappen'-Button an Navileisten, der in [[MediaWiki:Common.js]] implementiert wird */ .NavToggle { font-size: x-small; float: right; } /* Workaround für Internet Explorer 6 */ div.NavFrame, div.NavPic, .NavToggle { position: relative; } /* Stylesheet-Ergänzung zu SideBoxen (ehedem [[Wikipedia:TownBox|TownBox]]) */ div.sideBox { position: relative; float: right; background: white; margin-left: 1em; border: 1px solid gray; padding: 0.3em; width: 200px; overflow: hidden; clear: right; } div.sideBox dl { padding: 0; margin: 0 0 0.3em 0; font-size: 96%; } div.sideBox dl dt { background: none; margin: 0.4em 0 0 0; } div.sideBox dl dd { margin: 0.1em 0 0 1.1em; background-color: #f3f3f3; } /* Stylesheet-Ergänzung zu [[Wikipedia:Taxoboxen|Taxoboxen]] und [[Wikipedia:Paläoboxen|Paläoboxen]] */ table.taxobox, table.palaeobox { border-collapse: collapse; border: 1px solid gray; float: right; clear: right; margin-left: 0.5em; background-color: white; } table.taxobox th { background-color: #9bcd9b; } table.palaeobox th { background-color: #e7dcc3; } table.taxobox th, table.palaeobox th { border: solid 1px gray; text-align: center; font-weight: bold; } table.taxobox td, table.palaeobox td { vertical-align: top; } table.taxobox .Person, table.palaeobox .Person { font-style: normal; } table.taxobox div.thumb, table.taxobox div.thumb * { background-color: #f9f9f9; } table.taxobox div.thumb, table.taxobox div.thumb *, table.palaeobox div.thumb, table.palaeobox div.thumb * { margin: 0 auto; padding: 0; float: none; border: none; } table.taxobox div.magnify, table.palaeobox div.magnify { display: none; } table.taxobox tr td div.thumb div div.thumbcaption { text-align: center; } table.palaeobox tr td div.thumb div div.thumbcaption { text-align: left; } table.taxobox td.Person, table.palaeobox td.Person { text-align: center; display: block; } table.taxobox td.taxo-name, table.taxobox td.taxo-bild, table.palaeobox td.taxo-name, table.palaeobox td.taxo-bild, table.palaeobox td.taxo-zeit { text-align: center; } table.palaeobox td.taxo-ort { text-align: left; } /* aus Vorlage zur Entlastung, skinabhängigen Darstellung und Kombinierbarkeit hierher ausgelagert */ .wikitable, .prettytable { margin: 1em 1em 1em 0; background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse; } .prettytable th, .prettytable td { border: 1px #aaa solid; padding: 0.2em; } .prettytable th { text-align: center; } .prettytable caption { font-weight: bold; } /* Zebra-Tabellen */ table.wikitable.zebra tr:nth-child(even) { background: white; } .nogrid th, .nogrid td { border: none; } div.float-left, table.float-left, .float-left { float: left; clear: left; } div.float-right, table.float-right, .float-right { float: right; clear: right; margin: 1em 0 1em 1em; } div.centered, table.centered, .centered { margin-left: auto; margin-right: auto; } .toptextcells td { vertical-align: top; } /* Bitte KEINE weiteren Definitionen dieser Art für Boxen hier, das gehört in entsprechende Vorlagen! */ /* Hier 20 Mal Trivialitäten wie "text-align:center" zu definieren verlangsamt alles und ist nicht */ /* Sinn der Sache. (Und wer nicht weiß warum, hat's nicht verstanden.) */ /* Do not expand [[Wikipedia:WikiProjekt Georeferenzierung|kvaleberg.com-URLs]] for printing */ #content span.coordinates a.external.text:after, #content span.coordinates a.external.autonumber:after, #content div.coordinates a.external.text:after, #content div.coordinates a.external.autonumber:after { content: ""; } /* Do not expand URLs for printing */ #content span.plainlinks-print a.external.text:after, #content span.plainlinks-print a.external.autonumber:after, #content div.plainlinks-print a.external.text:after, #content div.plainlinks-print a.external.autonumber:after { content: ""; } /* Metadaten (bspw. [[Wikipedia:Personendaten|Personendaten]]) */ table.metadata { border: 1px solid #aaaaaa; display: none; } .metadata-label { color: #aaaaaa; } span.metadata, span.metadata-inline { display: none; } /* * Farbdefinitionen für Rahmen und Hintergründe von [[Wikipedia:Textbausteine|Textbausteinen]]. * Hier: Standardvorgaben für "dunkle Schrift auf hellem Grund". * Für Hell-auf-dunkel-Skins ([[MediaWiki:Amethyst.css|Amethyst]]) müssen dort entsprechende Definitionen * zusätzlich eingetragen werden! Anpassungen für andere Skins sind optional. * (Die Angaben der Rahmenstärke dienen der Bequemlichkeit, so dass man * für dünne Rahmen nur noch "border-style" angeben muss.) */ .rahmenfarbe1 { /* Wie Inhaltsverzeichnis */ border-color: #aaaaaa; border-width: 1px; } .rahmenfarbe2 { /* Unauffällig, geringer Kontrast */ border-color: #e9e9e9; border-width: 1px; } .rahmenfarbe3 { /* "Rot", auffällig */ border-color: #c00000; border-width: 1px; } .rahmenfarbe4 { /* Neutrale Farbe, deutlich */ border-color: #8888aa; border-width: 1px; } .rahmenfarbe5 { /* "Schwarz", hoher Kontrast */ border-color: #000000; border-width: 1px; } tr.hintergrundfarbe1 th, tr th.hintergrundfarbe1, table.hintergrundfarbe1, .hintergrundfarbe1 { /* Wie Inhaltsverzeichnis */ background-color: #f9f9f9; } tr.hintergrundfarbe2 th, tr th.hintergrundfarbe2, table.hintergrundfarbe2, .hintergrundfarbe2 { /* "Weiß", für Nicht-Artikel-Seiten, neutral */ background-color: #ffffff; } tr.hintergrundfarbe3 th, tr th.hintergrundfarbe3, table.hintergrundfarbe3, .hintergrundfarbe3 { /* "Gelb", auffällig */ background-color: #ffff40; } tr.hintergrundfarbe4 th, tr th.hintergrundfarbe4, table.hintergrundfarbe4, .hintergrundfarbe4 { /* Sehr auffällig */ background-color: #ffaa00; } tr.hintergrundfarbe5 th, tr th.hintergrundfarbe5, table.hintergrundfarbe5, .hintergrundfarbe5 { /* Neutral, abgesetzt */ background-color: #e0e0e0; } tr.hintergrundfarbe6 th, tr th.hintergrundfarbe6, table.hintergrundfarbe6, .hintergrundfarbe6 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b3b7ff; } tr.hintergrundfarbe7 th, tr th.hintergrundfarbe7, table.hintergrundfarbe7, .hintergrundfarbe7 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffcbcb; } tr.hintergrundfarbe8 th, tr th.hintergrundfarbe8, table.hintergrundfarbe8, .hintergrundfarbe8 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #ffebad; } tr.hintergrundfarbe9 th, tr th.hintergrundfarbe9, table.hintergrundfarbe9, .hintergrundfarbe9 { /* Allgemein „bunt“, für Hervorhebungen und Unterscheidungen */ background-color: #b9ffc5; } /* Keine Vergrößerung der Zeilenhöhe durch hochgestellte Zahlen der Fußnoten */ sup.reference { font-weight: 400; font-style: normal; } sup, sub { line-height: 1em; } /* Hervorhebung der angeklickten Fußnoten und der Rückverweise in blau */ ol.references > li:target, sup.reference:target { background-color: #def; } /* Hochgestellte Buchstaben in der Einzelnachweiseliste kursiv setzen */ ol.references li a[href|="#cite_ref"] { font-style: italic; } /* Inline-Verwendung der [[:Kategorie:Vorlage:Schwesterprojektverweis|Schwesterprojektverweise]] */ ol.references li div.sisterproject { display: inline !important; } /* Für <nowiki><hiero>…</hiero></nowiki> */ .mw-hierotable, .mw-hierotable th, .mw-hierotable td { border: 0; padding: 0; } /* Für [[MediaWiki:Anoneditwarning]] und weitere Hinweise, die alle untereinander stehen */ #mw-anon-edit-warning, #mw-missingsummary, #wp_talkpagetext { width: 80%; background: #d3e1f2; border: 1px solid #1a47ff; margin: 1em auto; padding: 1em; } /* Bei URLs, die auf unser Projekt und verwandte Projekte verweisen, den Pfeil ausblenden * Dieser Pfeil dient nur dazu, auf externe Ziele hinzuweisen * Auf den Einsatz der Klasse "plainlinks" kann dadurch verzichtet werden */ #content a[href^="http://de.wikipedia.org"], #content a[href^="http://toolserver.org"] { background: none !important; padding-right: 0 !important; } #content .mw-search-formheader div.search-types ul li a[href^="http://de.wikipedia.org"], #content .mw-search-formheader div.search-types ul li a[href^="http://toolserver.org"] { padding-right: 0.5em !important; } /* Falls bei der Seitenbearbeitung vergessen wurde, die Zusammenfassung auszufüllen */ .mw-summarymissed { border: 5px solid red; padding: 2px; } /* Copyrightwarnung */ #editpage-copywarn { border: solid 1px #c00000; font-size: 90%; background-color: #ffffff; } .mw-tos-summary { border: solid 1px #c00000; background-color: #ffffff; padding-left: 1em; } /* +++++ 2. SONSTIGE ANPASSUNGEN (Spezialseiten u. a.) +++++ */ /* Markierung von Redirects in [[Special:Allpages]], [[Special:Watchlist]], Kategorien */ .allpagesredirect, .watchlistredir, .redirect-in-category { font-style: italic; } /* Fettformatierung von Admin-Spezialseiten in [[Special:Specialpages]] abschalten */ .mw-specialpagerestricted strong { font-weight: normal; } /* Legende auf [[Special:Specialpages]] ebenfalls abschalten */ div.mw-specialpages-notes { display: none; } /* Größerer Abstand zwischen TOC-Nummerierung und TOC-Eintrag */ span.tocnumber { margin-right: 0.3em; } /* Skinabhängige absolute Positionierungen ausblenden */ /* Bitte [[MediaWiki Diskussion:Common.css#Absolute_Positionierungen]] beachten */ #coordinates, #coordinates_3_ObenRechts, #issnlink, #editcount, #shortcut, #artikelstadium, .topicon, #spoken-icon, #commons-icon { display: none; } /* Anpassungen für [[:Template:Link_FA]] */ /* hide the template */ #bodyContent span.FA { display: none; } /* change the bullets for links to special articles */ #p-lang li.FA { /* hier immer auch linkFA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/d/d0/Monobook-bullet-star-transparent.png"); } /* change the bullets for links to special articles */ #p-lang li.GA { /* hier immer auch linkGA_bullet in Common.js mit anpassen für die älteren skins! */ list-style-image: url("http://upload.wikimedia.org/wikipedia/commons/a/a1/Monobook-bullet-star-gray.png"); } /* Verhindere, dass Infoboxen etc. in den Inhalt von Kategorien hineinragen. Das betrifft nur Kategorieseiten. */ #mw-subcategories, #mw-pages { clear: both; } /* DIVs in ImageMaps inlinen (Vorschlag von Revolus) */ .imagemap-inline div { display: inline; } /* [[Special:Hochladen]]: Warnmeldung auf bestehende Dateien, unerwünschte Prefixe usw. deutlicher hervorheben. */ #wpDestFile-warning ul { border: solid red 1px; padding: 1.5em; } /* Warnmeldung für gesperrte Titel */ .mw-titleprotectedwarning { background-color: #eee; border: 2px solid red; padding: 1em; } /* Warnmeldung bei der Bearbeitung von Seiten im MediaWiki-Namensraum */ .mw-editinginterface { background-color: #f9f9f9; border-color: #c00000; border-width: 1px; border-style: solid; padding: 2px; } /* Überschrift 5. und 6. Ordnung proportionaler zu Fließtext */ #content h5 { font-size: 108%; /* Original: 116% */ } #content h6 { font-size: 100%; /* Original: 80% = kleiner als Bodytext, unschön */ } #content h6 .editsection { font-size: 120%; font-weight: normal; } /* Anleitung auf Special:Search */ .mw-searchresult { font-size: 84%; margin: 5px; } /* Gestaltung der Edittools-Leiste */ #specialchars { margin-top: 3px; border: solid 1px #aaaaaa; padding: 1px; text-align: left; background-color: white; } /* Legende für Versionsgeschichte */ .mw-history-legend { font-size: 90%; margin-top: 2px; margin-bottom: 2px; border: solid 1px #e9e9e9; padding: 0 5px 5px 5px; background-color: #f9f9f9; clear: both; } /* +++++ 3. NEUE [[Wikipedia:Hauptseite|HAUPTSEITE]] (ab 2006) +++++ */ /* Kategorie verbergen */ /* Überschrift verbergen */ /* Redirhinweis verbergen - ACHTUNG: Je nach Skin muss jetzt der Abstand zum oberen Rand korrigiert werden */ body.page-Wikipedia_Hauptseite #catlinks, body.page-Wikipedia_Hauptseite h1.firstHeading, body.page-Wikipedia_Hauptseite #contentSub { display: none; } #hauptseite h2 { background-color: #d8e8ff; border: 1px solid #8898bf; font-size: 1em; font-weight: bold; margin-top: 0; margin-bottom: 0; padding-top: 0.1em; padding-bottom: 0.1em; } #hauptseite .inhalt { background-color: #ffffff; border: 1px solid #8898bf; border-top: 0 solid white; padding: 0.3em 0.8em 0.4em 0.8em; } #hauptseite .inhalt hr { background-color: #8898bf; color: #8898bf; height: 1px; margin: 0.5em 0; padding: 0; } #hauptseite .inhalt .mehr { clear: both; font-size: 95%; margin-top: 0.8em; text-align: right; } #hauptseite table { background-color: transparent; } .hauptseite-oben, .hauptseite-links, .hauptseite-rechts { margin-bottom: 1em; } .hauptseite-links { margin-right: 0.5em; } .hauptseite-rechts { margin-left: 0.5em; } .hauptseite-oben h2, .hauptseite-unten h2 { text-align: center; } .hauptseite-oben .inhalt .portale { font-weight: bold; margin-top: 0.2em; margin-bottom: 0.2em; } .hauptseite-oben .inhalt .intern { font-size: 90%; text-align: center; } .hauptseite-links h2, .hauptseite-rechts h2 { text-indent: 0.8em; } #hauptseite-schwesterprojekte .inhalt a { font-weight: bold; } /* IPA links nicht unterstreichen */ .IPA a:link, .IPA a:visited { text-decoration: none; } /* CSS-Klassen für Schriftarten als Workaround für Defizite in alten IE-Versionen. * Achtung: IE6 mag keine Zeilenumbrüche zwischen den Fonts. * In IE8 nicht mehr nötig, soll mit den alten Versionen aussterben. Browserweiche: * http://www.dynamicsitesolutions.com/css/filters/star-html/ * http://www.dynamicsitesolutions.com/css/filters/first-child-plus-html/ */ * html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } *:first-child+html .Unicode { font-family: Code2000, Sun-ExtA, "Arial Unicode MS", NSimSun, sans-serif; } * html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } *:first-child+html .Unicode1 { font-family: Code2001, Quivira, "MPH 2B Damase", sans-serif; } * html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } *:first-child+html .Unicode2 { font-family: Sun-ExtB, Code2002, sans-serif; } * html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } *:first-child+html .IPA { font-family: Quivira, Code2000, Sun-ExtA, "DejaVu Sans", Gentium, Helvetica, "Arial Unicode MS", "Lucida Sans Unicode", sans-serif; } * html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } *:first-child+html .IAST { font-family: Code2000, SunExtA, "Arial Unicode MS", sans-serif; } * html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .altitalisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } *:first-child+html .gotisch { font-family: Quivira, Code2001, "MPH 2B Damase", sans-serif; } * html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } *:first-child+html .hebrew { font-family: Quivira, Sun-ExtA, "Arial Unicode MS", "SBL Hebrew", Code2000, "MPH 2B Damase", sans-serif; } * html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } *:first-child+html .spanAr { font-family: "Arial Unicode MS", Scheherazade, Code2000, "DejaVu Sans", sans-serif; } * html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } *:first-child+html .music-symbol { font-family: "Musical Symbols", Euterpe, Code2001, sans-serif; } * html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } *:first-child+html .polytonic { font-family: "Arial Unicode MS", "Palatino Linotype", Code2000, "New Athena Unicode", Gentium, "Athena Unicode"; } /* Standardmäßige Ausblendung der Flagged-Revisions-Backlog-Sitenotice */ #mw-oldreviewed-notice { display: none; } /* Standardmäßige Ausblendung der Flagged-Revisions-Kommentarbox */ #mw-commentbox { display: none; } /* Abstand zwischen Liste und Inhaltsverzeichnis erhöhen, siehe http://de.wikipedia.org/w/index.php?title=MediaWiki_Diskussion:Common.css&oldid=51639015#Abstand_vor_Inhaltsverzeichnis */ ul + .toc, ol + .toc { margin-top: 0.5em; } /* höheres Uploadfeld */ #wpUploadDescription { height: 20em; } /* Im Projekt WP:GEO benutzt die [[Vorlage:Coordinate]] das «geo-microformat» zur semantischen Auszeichnung des Texts. Der Inhalt dieses [[Tag (Informatik)|Tags]] ist nicht für den Leser bestimmt. */ .geo { display: none; } /* Patrollink ausblenden, da die Eweiterung hier nicht aktiviert ist und deren Optik zu sehr den gesichteten Versionen ähnelt. */ .fr-diff-patrollink, .patrollink { display: none; } /* Rollback-Knopf auf Beobachtungsliste ausblenden, da es dort nur von sehr beschränktem Nutzen ist und zu sehr vielen Reverts aus Versehen führt */ .page-Spezial_Beobachtungsliste .mw-rollback-link { display: none; } /* </source> */ /* Disable Discussion-tab */ #ca-talk { display: none; } /* reset code style */ code { background-color: none !important; border: none !important; border-radius: 0; padding: 0; } pre { white-space: pre; } /* highlighting */ .hb1 { background-color: #C1F5C1; } .hb2 { background-color: #CDC2EF; } .hb3 { background-color: #FFF6C9; } .hb4 { background-color: #FFC9C9; } .hb5 { background-color: #BED8ED; } .hb6 { background-color: #EDBBED; } .hb7 { background-color: #F4FDC7; } .hb8 { background-color: #FFE8C9; } .hf1 { color: #66D766; } .hf2 { color: #7C67C0; } .hf3 { color: #FFE879; } .hf4 { color: #FF7979; } .hf5 { color: #5D90B7; } .hf6 { color: #B857B8; } .hf7 { color: #E2F876; } .hf8 { color: #FFC679; } .he0 { border: 1px solid grey; border-radius: 4px; } .he1 { border: 1px solid #66D766; border-radius: 4px; } .he2 { border: 1px solid #7C67C0; border-radius: 4px; } .he3 { border: 1px solid #FFE879; border-radius: 4px; } .he4 { border: 1px solid #FF7979; border-radius: 4px; } .he5 { border: 1px solid #5D90B7; border-radius: 4px; } .he6 { border: 1px solid #B857B8; border-radius: 4px; } .he7 { border: 1px solid #E2F876; border-radius: 4px; } .he8 { border: 1px solid #FFC679; border-radius: 4px; } code { line-height: normal; } 0c63f7ca833485bd1164c4b5e198c15527d2c6a2 Datei:Ecl tagesprogramm.jpg 6 717 1672 2021-09-07T09:26:22Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus bitlenhisto1.png 6 718 1673 2021-09-07T09:26:33Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus bitlenhisto2.png 6 719 1674 2021-09-07T09:27:11Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus bitlenhisto3.png 6 720 1675 2021-09-07T09:27:20Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus frames overlay.png 6 721 1676 2021-09-07T09:27:27Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus idle.png 6 722 1677 2021-09-07T09:27:35Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus message.png 6 723 1678 2021-09-07T09:27:44Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus message decoded.png 6 724 1679 2021-09-07T09:27:52Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus message sample.png 6 725 1680 2021-09-07T09:28:01Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus packets.png 6 726 1681 2021-09-07T09:28:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus receive.png 6 727 1682 2021-09-07T09:28:17Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus receive frame.png 6 728 1683 2021-09-07T09:28:28Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus receive timing.png 6 729 1684 2021-09-07T09:28:45Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus timing.png 6 730 1685 2021-09-07T09:28:59Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus transmit.png 6 731 1686 2021-09-07T09:29:07Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus unknown timings.png 6 732 1687 2021-09-07T09:29:28Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ecl bus data.zip 6 733 1688 2021-09-07T11:36:34Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 ECL-Bus-Protokoll 0 734 1689 2021-09-07T11:38:00Z Chris 2 Seite erstellt wikitext text/x-wiki Neue Erfahrungen bringen neue Sichtweisen. Unter dieser Prämisse - und nachdem ich den Artikel des [[ECL-Bus-Decoder]]s selbst nicht mehr ganz verstanden habe - entschied ich mich, das Ganze nochmal anzuschauen. Worum geht es? Bei der Heizungsanlage meiner Eltern - genauer einer Grundwasser-Wärmepumpe - ist ein Regler von Danfoss verbaut. Genauer ein ECL 300. Dieser verwendet zur Kommunikation mit seinen externen Modulen den so genannten ECL-Bus, der zwar in der Anleitung erwähnt, aber keine weiteren Details genannt werden. Auch der Support von Danfoss schwieg sich bei einer Anfrage vor einigen Jahren darüber (und die RS-232-Schnittstelle an der Front des ECL 300) aus: "Es gibt keine Dokumentation". Oder vielmehr: Es gibt keine Dokumentation, die für die Öffentlichkeit bestimmt ist. "Kein Problem, dann mach ich halt eine" war mein Gedanke damals, woraufhin der oben genannte Artikel entstand. =Busteilnehmer= Lt. meiner Recherchen gibt/gab es folgende Geräte für das System (untersuchte sind fett markiert): * '''ECL 300''': elektronischer Temperaturregler (ECL 301 ist die 24 V-Version) * '''ECA 60''': Raumleitgerät mit Temperaturmessung * ECA 62: Raumleitgerät mit Temperatur- und Luftfeuchtemessung * ECA 61/63: Im Prinzip wie ECA 60/62, nur werden diese als "Remote control" statt "Room panels" bezeichnet * '''ECA 86''': Temperatur-Alarm- & Relaismodul für ECL 30x (4x Temperatur, 2x Relais) ==ECL 300== [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Der/Die/Das ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. ==ECA 86== [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt. ==ECA 60== [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEPROM 93C66A (512x8 bit) gespeichert. Auf der Rückseite des Gerätes befindet sich ein Schalter zum Wählen der Adresse (A und B), ein Umschalten auf B bezweckt lediglich, dass das Raumleitgerät ewig im Init-Zustand (keine Anzeige von Messwerten) bleibt. =Einbaumodule= Ferner bin ich über folgende Einsteckmodule für die ECL 30x gestoßen: * ECA 71: Modbus-Adapter für die ECL 30x * ECA 81: RS-232-Adapter für die ECL 30x * ECA 87: RS-232-Datenlogger In der Anleitung des ECA 81 wird gleich auf der ersten Seite darauf hingewiesen ''"Es ist kein Protokoll für die ECA 81 RS 232 Kommunikation vorhanden. ECA 81 dient nur der Kommunikation mit der DAnfoss ECL Comfort Service Software."'' Die Anleitung des ECA 87 beinhaltet die Information, dass die Einsteckmodule (u. a.?) über SPI kommunizieren - und immerhin ist das Protokoll dafür beschrieben. Am Frontpanel der ECL 30x befindet sich allerdings schon eine RS-232-Schnittstelle, die allerdings ein anderes Protokoll spricht. In dem Sinne: Danke für nichts. =Schnittstelle= Wie eingangs angedeutet, gibt es nicht sonderlich viele öffentlich verfügbare Informationen über die Schnittstelle. Aus der Installationsanleitung lässt sich allerdings drauf schließen, dass es ein eindrahtiges Bus-System ist: Am Regler ist Klemme 15 mit "BUS" gekennzeichnet, Klemme 16 mit GND (an der auch die Temperaturfühler terminiert sind). ==Physischer Layer== Da die Raumleitgeräte keine eigene Versorgung haben ist ferner anzunehmen, dass es eine Phantomspeisung gibt. Mit dem Multimeter ließen sich um die 24 V Wechselspannung mit 50 Hz messen, also spricht nichts dagegen, auch mal das Oszi anzuklemmen. Im Ruhezustand bestätigt das Oszi in etwa das, was das Multimeter gemessen hat: Ein 50 Hz-Rechteck-Signal mit etwa 26 V Amplitude und 64 % Duty-Cycle: <gallery> ecl_bus_idle.png | Signalverlauf des ECL-Bus im Ruhezustand </gallery> Drückt man oft genug auf Run/Stop erwischt man auch mal ein bisschen mehr Gezappel als die 50 Hz: <gallery> ecl_bus_transmit.png | ecl_bus_timing.png | </gallery> Mit ein bisschen mehr Zoom lassen sich auch die mutmaßlichen Bitdauern messen - 2,06 ms für 5 Zustandswechsel ergibt 412 µs / "Bit". Mutmaßlich und in Anführungszeichen, da noch nicht bekannt sind, wie genau die Daten übertragen werden. Ist man mit der Run/Stop-Taste geduldiger als mit dem Einstellen eines cleveren Triggers, bekommt man irgendwann folgendes auf den Schirm: <gallery> ecl_bus_receive.png | ecl_bus_receive_frame.png | ecl_bus_receive_timing.png | </gallery> Das sieht doch schon eher nach vollständiger Nachricht aus. Auffällig ist zudem, dass die Pegel der Kommunikation ein Stück niedriger sind als in den Screenshots weiter oben (und zum 50 Hz-Rechteck). Das könnte ein Unterschied zwischen den Teilnehmern sein: Angenommen das zuvor gezeigte Signal ist vom ECL 300, dann ist es naheliegend, dass die selbe Schaltung Versorgung (Erzeugung der 50 Hz) wie zur Kommunikation verwendet wird. Ein Busteilnehmer, insbesondere wenn dieser über den Bus gespeist wird, hat eine andere (tendenziell niedrigere) Spannung, mit der der Bus getrieben werden kann. Beim Blick auf ein Frame auch wieder eine Messung der mutmaßlichen Bitlänge: 3,3 ms für 8 Übergänge = 412,5 µs / "Bit", also sehr nah am Wert von oben. ==Bitübertragung== Aufzeichnungen vom Oszilloskop sind etwas dröge in Sachen Protokoll-Reverse-Engineering - zumindest, wenn man es auch mit einem Logic-Analyzer machen kann. Als Schnittstelle zum LA dient (wie bereits vorher erfolgreich getestet) ein einfacher Optokoppler mit passenden Vorwiderständen. Neben den üblichen Aufzeichnungen mit verschiedenen Aktionen am Gerät lief die Aufzeichnungen auch einfach mal für 10 Minuten ohne besondere Aktivität. Mit ein bisschen Excel-Datenschubserei purzelten zwei Histogramme über die Häufigkeit der verschiedenen Zustandsdauern heraus: <gallery> ecl_bus_bitlenhisto1.png | Histogramm über alle Bitlängen ecl_bus_bitlenhisto2.png | Histogramm über Bitlängen bis 1 ms ecl_bus_bitlenhisto3.png | Histogramm mit besonderer X-Achse </gallery> Zu berücksichtigen ist, dass Low- und High-Zustände gleich dargestellt sind. Im ersten Diagramm sieht man halbwegs gut, dass die Zustände um 7,2 ms und 12,8 ms weitaus am häufigsten eingenommen werden (hier sollte die Kombination aus logarithmischer Skala und Clustergröße 0,001 ms im Hinterkopf behalten werden). In der Summe der beiden Zahlen findet man die Periodendauer der 50 Hz der Versorgung wieder. Schaut man sich einen deutlich kleineren Wertebereich (zweites Diagramm) an sieht man, dass sich bei 0,4-nochwas und 0,8-nochwas Millisekunden mit etwas Phantasie [[wpde:Normalverteilung|normalverteilte Kurven]] ergeben. Dass die zweite "Glocke" bei doppelte Zustandsdauer der ersten hat ist kein Zufall, wählt man bei für die X-Achse ein Intervall von 0,412 ms, sieht man schön die vorher mit dem Oszilloskop bestimmten mutmaßlichen Bitlängen. Woher die Häufungen bei "+0,5" (also 1,5-, 3,5-, ...-facher) Bitlängen herkommt, kann man anhand der Datenlage nicht pauschal sagen; hier hilft ein genauerer Blick in die Aufzeichnung: <gallery> ecl_bus_unknown_timings.png </gallery> An der Stelle hatte ich direkt das Glück, zwei solcher "+0,5"-Bitlängen zu erwischen. Wie es scheint ist das einfach ein wenig Padding hinter den eigentlichen Daten. Aber zu den Daten selbst - scrollt man durch die Aufzeichnung sieht man, dass die Frames immer in Rudeln von 5 kommen: <gallery> ecl_bus_packets.png | Zwei Nachrichten ecl_bus_message.png | Eine Nachricht im Detail </gallery> Nimmt man aus dem zweiten Screenshot die einzelnen Frames und legt sie in Bildbearbeitung übereinander, bekommt man sowas ähnliches wie ein Augendiagramm, das ein bisschen bekannt vorkommt: <gallery> ecl_bus_frames_overlay.png | Alle Frames einer Nachricht überlagert </gallery> erstes Bit immer low, letztes Bit immer low, riecht nach UART - allerdings mit etwas ungewöhnlichen 16 Bit Symbollänge. Die vorhin bestimmten etwa 412 µs Bitlänge entspricht etwa 2400 Baud, den Analyzer in Logic damit gefüttert ergibt Daten: <gallery> ecl_bus_message_decoded.png | Eine Nachricht </gallery> Exportiert man die Daten des Analyzers, bekommt man neben sehr vielen <code>0x0000</code> auch zum Beispiel folgendes: <pre>Zeit Daten ... 20,25630025 0x0000 20,27630175 0x60EF 20,29630150 0x1915 20,31630525 0x0CA8 20,33631175 0x0023 20,35631150 0x0D54 20,37631200 0x0000 20,39631075 0x60EF 20,41631625 0x1952 20,43631700 0x6000 20,45631275 0x0045 20,47631425 0x0D5F 20,49632000 0x0000 ... </pre> Zu beachten ist, dass - wie bei UART üblich - das LSB zuerst kommt. Natürlich war ich anfangs nicht so clever und habe ein Python-Script (basierend auf meinem alten C-Code) zum Analysieren der rohen Aufzeichnungen gebastelt. Das Script ist im Abschnitt Downloads zu finden. Dieses kann die Daten wie folgt ausspucken: <pre>12.956395 0x04AF 0x0B1A 0x0000 0x0000 0x0DD8 19.236316 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 20.276302 0x60EF 0x1915 0x0CA8 0x0023 0x0D54 20.396311 0x60EF 0x1952 0x6000 0x0045 0x0D5F 24.036128 0x01F0 0x0A1E 0x22FA 0x0000 0x0D35 25.635993 0x02F0 0x1512 0x030B 0x6779 0x0D07 41.754978 0x04AF 0x0B11 0x0000 0x0000 0x0DCF 42.054995 0x09AF 0x0005 0x0000 0x0000 0x0DBD 42.194992 0x09FA 0xFF0F 0xFFFF 0x00F0 0x0DFF 48.034069 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 49.073926 0x60EF 0x1921 0x0CAB 0x0023 0x0D63 49.193916 0x60EF 0x194B 0x6000 0x0045 0x0D58 52.833398 0x01F0 0x0A1D 0x22FA 0x0000 0x0D34 54.433216 0x02F0 0x152F 0x030B 0x6779 0x0D24 </pre> =Protokoll= Die übliche Vorgehensweise beim Reverse Engineering eines Protokolls ist, bekannte Informationen zu erkennen bzw. zu erzeugen und wiederzufinden. Aufgrund der zurückliegenden Untersuchung des Protokolls kann diese Phase stark abgekürzt werden - das Rad muss schließlich nicht jedes Mal neu erfunden werden. Wer den alten Artikel kennt oder parallel geöffnet hat, wird vermutlich schon erkannt haben, dass die [[wpde:Byte-Reihenfolge|Byte-Reihenfolge]] der Frames unterschiedlich ist. Um ehrlich zu sein: das ist mir damals nicht wirklich aufgefallen, da der Sprung von roher Datenanalyse zum Interpretieren (im AVR) sehr kurz war. Durch die Nichtbeachtung der Endianness bei der Erfassung, Verarbeitung und Ausgabe ging der Punkt einfach verloren. Auch ein Grund, sich nochmal damit auseinanderzusetzen. ==Header== Schaut man sich im letzten Abschnitt den Auszug das Beispiel genauer an, sieht man zumindest im ersten Symbol (bzw. Word) der Daten eine gewisse Wiederholung. Ein einfacher Trick um einen beschränkten Datenraum zu finden ist die Funktion "Duplikate entfernen" in Excel, nachdem die Symbole in Spalten aufgeteilt sind. Während den verschiedenen Aufzeichnungen ließen sich 11 unterschiedliche Nachrichtentypen identifizieren. Hierbei beinhaltet das niederwertige Byte des ersten Word Sender und Empfänger der Nachricht - das höherwertige Nibble ist der Sender, das niederwertige der Empfänger: {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || ECA 60 |- | E || ECA 86 |- | F || ECL 300 |} Höherwertige Byte des ersten Word entspricht dem Nachrichtentyp: {| class="wikitable sortable" |- ! d[0] !! Typ !! Sender !! Empfänger !! Bezeichnung !! Häufigkeit |- | <code>0x04AF</code> || 04 || A || F || Innentemperatur (ECA 60) || 125/h |- | <code>0x05AF</code> || 05 || A || F || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || - |- | <code>0x09AF</code> || 09 || A || F || Abfrage Tagesprogramm || 63/h |- | <code>0x11AF</code> || 11 || A || F || Zeit setzen || - |- | <code>0x60EF</code> || 60 || E || F || Temperaturfühler ECA 86 || 125/h |- | <code>0x01F0</code> || 01 || F || 0 || Außentemperatur || 125/h |- | <code>0x02F0</code> || 02 || F || 0 || Aktuelle Zeit || 125/h |- | <code>0x05FA</code> || 05 || F || A || Solltemperatur am ECL 300 setzen || - |- | <code>0x06FA</code> || 06 || F || A || Bestätigung Setzen Solltemperatur (Antwort auf 05AF) || - |- | <code>0x09FA</code> || 09 || F || A || Tagesprogramm (Antwort auf 06AF) || 63/h |- | <code>0x62FE</code> || 62 || F || E || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine einstündige Datenerfassung, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. ==Prüfsumme== Das höherwertige Byte im letzten Word habe ich immer mit 0x0D beobachtet, das niederwertige Byte ist eine Prüfsumme, die sich als Summe aller Bytes des Headers und der Nutzdaten berechnet: <source lang="javascript"> var data = [ 0x0100, 0x0302, 0x0504, 0x0706, 0x091C ]; var checksum_calc = 0; var checksum_msg = data[4] & 0xFF; for(var i = 0; i < 4; i++) { checksum_calc += (data[i] >> 8) & 0xFF; checksum_calc += (data[i] >> 0) & 0xFF; } checksum_calc &= 0xFF; console.log("calculated checksum: 0x%s, explected 0x%s", checksum_calc.toString(16), checksum_msg.toString(16) ) </source> Wie man darauf kommt fragt ihr? Ausprobieren und ein bisschen Glück. Die "low hanging fruits" sind in Summe, XOR und CRC - bei letzterem kommt allerdings die Schwierigkeit, dass man den passenden Startwert und Polynom finden muss. Bei CRC-8 sind das theoretisch 65536 Kombinationen (wobei für das Polynom auf bestimmte Werte eingeschränkt werden kann). Wird CRC-16 (oder höhere) verwendet, wird die Anzahl der möglichen Kombinationen deutlich größer. ==Payload== Die 3 Words "in der Mitte" sind die eigentlichen Nutzdaten Die Positionsangaben (d[x]) beziehen sich auf dem 0-basierten Index des Words im Paket, die Angabe "Word x" ist ebenfalls 0-basiert. Beispiel: [[Datei:ecl_bus_message_sample.png]] <code> <span style="color: lightgrey"> 04 AF </span> 0B 1A 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 00001011 00011010 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?!!!!!!! !!!!!!!! 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> In der ersten Zeile sind die Werte der Bytes Hexadezimal dargestellt (Little Endian), das zuerst übertragene Word befindet sich links. Die zweite Zeile beinhaltet die binäre Entsprechung des obigen Wertes. Vergleicht man diese Zeile mit dem oben dargestellten Signal auf der Busleitung, ist jedes Word rückwärts abgebildet (LSB first auf dem Bus, MSB first im Text) Die dritte Zeile stellt die "Bekanntheit" des jeweiligen Bits dar: *!: Bedeutung bekannt *?: Bedeutung unbekannt *0: immer low *1: immer high ===04AF: Innentemperatur=== Diese Nachricht überträgt die am ECA 60 gemessene Temperatur an das ECL 300, wo es als Führungsgröße verwendet werden kann <code> <span style="color: lightgrey"> 04 AF </span> <span class="hb1"> 0B 1A </span> 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 0<span class="hb1">0001011 00011010</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?<span class="hb1">!!!!!!! !!!!!!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:0</span></code> || Innentemperatur || x / 128 || 0x0B1A || 22.2<s>03125</s> °C |} Die theoretische Auflösung der Temperatur beträgt 7,8 m°C, wobei der Wert sicher nicht die Genauigkeit hat. Eine Nachkommastelle reicht. Negative Werte werden vermutlich über das aktuell mit ? markierte MSB im Zweierkomplement, was noch bestätigt werden muss. ===05AF/05FA: Solltemperatur, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit)=== *0x05AF: Solltemperatur am ECA 60 setzen, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) *0x05FA: Solltemperatur am ECL 300 setzen <code> <span style="color: lightgrey"> 05 AF </span> <span class="hb1"> 2C </span> FF <span class="hb2"> 0C </span> 24 <span class="hb3"> </span> 82<span class="hb4"> </span> <span class="hb5"> 00 </span> <span style="color: lightgrey"> 0D 91 </span> <span style="color: lightgrey">00000101 10101111</span> 00<span class="hb1">10110</span>0 11111111 0<span class="hb2">000110</span>0 00100100 <span class="hb3">1</span>0000<span class="hb4">010</span> <span class="hb5">0000000</span>0 <span style="color: lightgrey">00001101 10010001</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00<span class="hb1">!!!!!</span>0 ???????? !<span class="hb2">!!!!!!</span>0 ???????? <span class="hb3">!</span>0000<span class="hb4">!!!</span> <span class="hb5">!!!!!!!</span>0 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.13:9</span></code> || Soll-Temperatur || x || 0x16 || 22 °C |- | <code><span class="hb2">2.14:9</span></code> || Abweichende Temperatur (Entspannen) || (s. u.) || 0x06 || +6 °C |- | <code><span class="hb3">3.15</span></code> || Abweichung aktiv || s. u. || 0x01 || aktiv |- | <code><span class="hb4">3.10:8</span></code> || Betriebsmodus || s. u. || || 2 = Konstante Komforttemperatur |- | <code><span class="hb5">3.7:1</span></code> || Abweichende Temperatur (Abwesenheit) || (s. u.) || 0x00 || 0 °C |} Achtung: hier gibt es noch eine kleine Unsicherheit, was <code>1.7:0</code> macht und wie es zu <code><span class="hb1">1.13:9</span></code> steht. ====Abweichende Temperatur==== In den Words <code><span class="hb2">2.14:9</span></code> und <code><span class="hb5">3.7:1</span></code> sind die Abweichungen zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gelten. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - im Byte um ein Bit nach links verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement beachtet werden. Um vorzeichenbehaftete 8 Bit Integer verwenden zu können, werden im Code die folgenden Bits ersetzt: <source lang="C"> if(type == ECL_DIFF_RELAX) { ecl_data.tmp_diff = (buff[2] >> 9) & 0x7F; if(ecl_data.tmp_diff & 0x20) { ecl_data.tmp_diff |= 0xC0; } } else if(type == ECL_DIFF_AWAY) { ecl_data.tmp_diff = (buff[3] >> 1) & 0x7F; if(ecl_data.tmp_diff & 0x40) { ecl_data.tmp_diff |= 0x80; } } </source> Das Setzen von Abweichungen ist etwas merkwürdig: Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und Wiederverbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEPROM des ECA 60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5 °C bei Abwesenheit oder -10 °C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern. ====Betriebsmodus==== {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Manuell |- | 001 || 1 || Zeitgesteuerter Betrieb |- | 010 || 2 || Konstante Komforttemperatur |- | 011 || 3 || Konstante reduzierte Temperatur |- | 100 || 4 || Standby |} Die restlichen zustände sind mir nicht bekannt. ===06AF/06FA: Bestätigung Setzen Solltemperatur (Antwort auf 05AF)=== Diese Nachricht dient offenbar der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (06FA folgt auf 05AF bw. 06AF folgt auf 05FA) direkt nach einem 05**-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden. ===09AF: Abfrage Tagesprogramm=== Abfrage des Tagesprogrammes für den Heizkreis durch ECA 60. <code> <span style="color: lightgrey"> 09 AF </span> 00 04<span class="hb1"> </span> 00 00 00 00 <span style="color: lightgrey"> 0D BC </span> <span style="color: lightgrey">00001001 10101111</span> 00000000 00000<span class="hb1">100</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 10111100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00000000 00000<span class="hb1">!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.2:0</span></code> || Wochentag || 0=Montag ... 7=Sonntag || 0x04 || Freitag |} Die Ermittlung des Wochentags ist eigentlich klare Sache, aber der Vollständigkeit halber: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Montag |- | 001 || 1 || Dienstag |- | 010 || 2 || Mittwoch |- | 011 || 3 || Donnerstag |- | 100 || 4 || Freitag |- | 101 || 5 || Samstag |- | 110 || 6 || Sonntag |} ===09FA: Rückmeldung Tagesprogramm=== Rückmeldung des Heizkreis-Tagesprogrammes auf Abfrage in 09AF. <code> <span style="color: lightgrey"> 09 FA </span> <span class="hb1"> FF 3F 81 FF 00 FE </span> <span style="color: lightgrey"> 0D BF </span> <span style="color: lightgrey">00001001 11111010</span> <span class="hb1">11111111 00111111 10000001 11111111 00000000 11111110</span> <span style="color: lightgrey">00001101 10111111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:3.0</span></code> || Tagesprogramm als Bitmap || s. u. || s. u. |} Hier habe ich echte Zweifel bekommen, ob die Endianness richtig ist. Um kurz die Fakten zu nennen: Jedes Bit entspricht eine halbe Stunde, in dem Beispiel gibt es zwei Heizphasen: [[Datei:ecl_tagesprogramm.jpg]] also: *04:30 - 08:30 *11:30 - 23:00 Um die Bitmap intuitiver zu bekommen, ist es am einfachsten, die Endianness zu ändern - so wird aus dem Beispiel von oben: <code> <span class="hb1"> 0xFF3F </span><span class="hb2"> 0x81FF </span><span class="hb3"> 0x00FE </span> LE: <span class="hb1">1111111100111111</span><span class="hb2">1000000111111111</span><span class="hb3">0000000011111110</span> BE: <span class="hb1">0011111111111111</span><span class="hb2">1111111110000001</span><span class="hb3">1111111000000000</span> </code> So wird schon eher ein Schuh draus: rechts ist 00:00, links 24:00 - das deckt sich mit der Darstellung oben. ===11AF/02F0: Zeit setzen/aktuelle Zeit=== <code> <span style="color: lightgrey"> 11 AF </span> <span class="hb1"> 03 </span> <span class="hb2"> 20 </span> <span class="hb3"> 05 </span> <span class="hb4"> 0D </span> <span class="hb5"> 7</span><span class="hb6">9 </span> <span class="hb7"> 79 </span> <span style="color: lightgrey"> 0D E7 </span> <span style="color: lightgrey">00010001 10101111</span> 0<span class="hb1">0000011</span> 0<span class="hb2">0100000</span> 00<span class="hb3">000101</span> 00<span class="hb4">001101</span> 0<span class="hb5">111</span><span class="hb6">1001</span> <span class="hb7">01111001</span> <span style="color: lightgrey">00001101 11100111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 0<span class="hb1">!!!!!!!</span> 0<span class="hb2">!!!!!!!</span> 00<span class="hb3">!!!!!!</span> 00<span class="hb4">!!!!!!</span> ?<span class="hb5">!!!</span><span class="hb6">!!!!</span> <span class="hb7">!!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:8</span></code> || Minuten || x || 0x03 || 3 |- | <code><span class="hb2">1.6:0</span></code> || Sekunden || x || 0x20 || 32 |- | <code><span class="hb3">2.13:8</span></code> || Tag || x || 0x05 || 5 |- | <code><span class="hb4">2.5:0</span></code> || Stunden || x || 0x0D || 13 |- | <code><span class="hb5">3.15:12</span></code> || Wochentag || 1=Montag ... 7=Sonntag || 0x07 || Sonntag |- | <code><span class="hb6">3.11:8</span></code> || Monat || x || 0x09 || 9 |- | <code><span class="hb7">3.7:0</span></code> || Jahr || 1900 + x || 0x79 || 2021 |} In dieser Nachricht wird also Sonntag, 2021-09-05 13:03:32 als aktuelles Datum & Zeit gesetzt. Die Sekunden können zumindest am ECA 60 nicht eingestellt werden. Bemerkenswert ist hier, dass bei dieser Nachricht der Wochentag nicht wie in Nachricht 0x09AF nicht bei 0, sondern bei 1 beginnt. Eine Vermutung könnte sein, dass ein Wert von "0" die ECL 300 veranlasst, den Wochentag selbst zu berechnen, was ich jedoch nicht beobachten konnte. Wieder der Vollständigkeit halber hier die Lookup-Tabelle der Wochentage: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 001 || 1 || Montag |- | 010 || 2 || Dienstag |- | 011 || 3 || Mittwoch |- | 100 || 4 || Donnerstag |- | 101 || 5 || Freitag |- | 110 || 6 || Samstag |- | 111 || 7 || Sonntag |} ===60EF: Temperaturfühler ECA 86=== Mit dieser Nachricht werden die vom ECA 86 gemessenen Temperaturen übertragen. Das Modul verfügt über 4 Sensoreingänge, die Übertragung der Messwerte erfolgt in zwei Nachrichten. <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1E DB </span> <span class="hb2"> 0B 96 </span> 00 <span class="hb3"> 2</span><span class="hb4">3 </span> <span style="color: lightgrey"> 0D 0C </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011110 11011011</span> <span class="hb2">00001011 10010110</span> 00000000 <span class="hb3">0010</span><span class="hb4">0011</span> <span style="color: lightgrey">00001101 00001100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> <span class="hb2">!!!!!!!! !!!!!!!!</span> 00000000 <span class="hb3">!!!!</span><span class="hb4">!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1EDB || 61,7<s>109375</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x0B96 || 23,1<s>71875</s> °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x02 || 2 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x03 || 3 |} Für die zweite Gruppe sieht die Nachricht wie folgt aus: <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1F 2F </span> <span class="hb2"> 60 00 </span> 00 <span class="hb3"> 4</span><span class="hb4">5 </span> <span style="color: lightgrey"> 0D 42 </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011111 00101111</span> <span class="hb2">01100000 00000000</span> 00000000 <span class="hb3">0100</span><span class="hb4">0101</span> <span style="color: lightgrey">00001101 01000010</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1F2F || 62,3<s>671875</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x6000 || 192 °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x04 || 4 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x05 || 5 |} Index 1 und 2 konnten noch nicht beobachtet werden, Index 5 entspricht dem ungenutzten Eingang 4, der mit einem Widerstand terminiert ist. Dementsprechend ist davon auszugehen, dass die Indizes einfach um 2 verschoben sind. ===01F0: Außentemperatur=== <code> <span style="color: lightgrey"> 01 F0 </span> <span class="hb1"> 0A 06 </span> <span class="hb2"> 2</span>2 <span class="hb3"> </span> FA 00 00 <span style="color: lightgrey"> 0D 1D </span> <span style="color: lightgrey">00000001 11110000</span> <span class="hb1">00001010 00000110</span> 00<span class="hb2">10</span>00<span class="hb3">10</span> 11111010 00000000 00000000 <span style="color: lightgrey">00001101 00011101</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> ??<span class="hb2">!!</span>??<span class="hb3">!!</span> ???????? 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Außentemperatur || x / 128 || 0x0A06 || 20,0<s>46875</s> °C |- | <code><span class="hb2">2.13:12</span></code> || Betriebsmodus Brauchwasserkreis || s. u. || 0x02 || Komforttemperatur |- | <code><span class="hb3">2.9:8</span></code> || Betriebsmodus Heizkreis || s. u. || 0x02 || Komforttemperatur |} Der Betriebsmodus wird vermutlich nach folgender Tabelle bestimmt: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Reduzierte Temperatur |- | 01 || 1 || Optimierte Aufheizphase |- | 10 || 2 || Komforttemperatur |- | 11 || 3 || Optimierte Absenkphase |} Bisher habe ich nur Modus 0 und 2 gesehen, die anderen beiden stammen aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet. ===62FE: Setzen Relais an ECA 86=== <code> <span style="color: lightgrey"> 62 FE </span> FF FF FF FF 00 00 <span style="color: lightgrey"> 0D 5C </span> <span style="color: lightgrey">01100010 11111110</span> 11111111 11111111 11111111 11111111 00000000 00000000 <span style="color: lightgrey">00001101 01011100</span> </code> Da die Heizung während der Aufzeichnungen nie aktiv war, gibt es hierzu noch keine Informationen. ===Alarmmodul=== Das Alarmmodul ist leider nicht am ECL Bus (sondern am ECL 300) angeschlossen, auch konnte ich keine Nachrichten ausmachen, in dem ein etwaiger Alarmzustand übertragen wird. Dadurch ist die Ferndiagnose über den ECL-Bus leider in weite Ferne gerückt. =Downloads= * [[Datei:Ecl_bus_data.up]] Aufzeichnungen (Saleae Logic 2.3.35), gefilterte, und gesparste Daten und Python-Scripts zum Filtern/Parsen 9d8ddadc05c37156f62d3a43d2b097ecdb0f6346 ECL-Bus-Protokoll 0 734 1690 1689 2021-09-07T11:39:51Z Chris 2 /* Downloads */ wikitext text/x-wiki Neue Erfahrungen bringen neue Sichtweisen. Unter dieser Prämisse - und nachdem ich den Artikel des [[ECL-Bus-Decoder]]s selbst nicht mehr ganz verstanden habe - entschied ich mich, das Ganze nochmal anzuschauen. Worum geht es? Bei der Heizungsanlage meiner Eltern - genauer einer Grundwasser-Wärmepumpe - ist ein Regler von Danfoss verbaut. Genauer ein ECL 300. Dieser verwendet zur Kommunikation mit seinen externen Modulen den so genannten ECL-Bus, der zwar in der Anleitung erwähnt, aber keine weiteren Details genannt werden. Auch der Support von Danfoss schwieg sich bei einer Anfrage vor einigen Jahren darüber (und die RS-232-Schnittstelle an der Front des ECL 300) aus: "Es gibt keine Dokumentation". Oder vielmehr: Es gibt keine Dokumentation, die für die Öffentlichkeit bestimmt ist. "Kein Problem, dann mach ich halt eine" war mein Gedanke damals, woraufhin der oben genannte Artikel entstand. =Busteilnehmer= Lt. meiner Recherchen gibt/gab es folgende Geräte für das System (untersuchte sind fett markiert): * '''ECL 300''': elektronischer Temperaturregler (ECL 301 ist die 24 V-Version) * '''ECA 60''': Raumleitgerät mit Temperaturmessung * ECA 62: Raumleitgerät mit Temperatur- und Luftfeuchtemessung * ECA 61/63: Im Prinzip wie ECA 60/62, nur werden diese als "Remote control" statt "Room panels" bezeichnet * '''ECA 86''': Temperatur-Alarm- & Relaismodul für ECL 30x (4x Temperatur, 2x Relais) ==ECL 300== [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Der/Die/Das ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. ==ECA 86== [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt. ==ECA 60== [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEPROM 93C66A (512x8 bit) gespeichert. Auf der Rückseite des Gerätes befindet sich ein Schalter zum Wählen der Adresse (A und B), ein Umschalten auf B bezweckt lediglich, dass das Raumleitgerät ewig im Init-Zustand (keine Anzeige von Messwerten) bleibt. =Einbaumodule= Ferner bin ich über folgende Einsteckmodule für die ECL 30x gestoßen: * ECA 71: Modbus-Adapter für die ECL 30x * ECA 81: RS-232-Adapter für die ECL 30x * ECA 87: RS-232-Datenlogger In der Anleitung des ECA 81 wird gleich auf der ersten Seite darauf hingewiesen ''"Es ist kein Protokoll für die ECA 81 RS 232 Kommunikation vorhanden. ECA 81 dient nur der Kommunikation mit der DAnfoss ECL Comfort Service Software."'' Die Anleitung des ECA 87 beinhaltet die Information, dass die Einsteckmodule (u. a.?) über SPI kommunizieren - und immerhin ist das Protokoll dafür beschrieben. Am Frontpanel der ECL 30x befindet sich allerdings schon eine RS-232-Schnittstelle, die allerdings ein anderes Protokoll spricht. In dem Sinne: Danke für nichts. =Schnittstelle= Wie eingangs angedeutet, gibt es nicht sonderlich viele öffentlich verfügbare Informationen über die Schnittstelle. Aus der Installationsanleitung lässt sich allerdings drauf schließen, dass es ein eindrahtiges Bus-System ist: Am Regler ist Klemme 15 mit "BUS" gekennzeichnet, Klemme 16 mit GND (an der auch die Temperaturfühler terminiert sind). ==Physischer Layer== Da die Raumleitgeräte keine eigene Versorgung haben ist ferner anzunehmen, dass es eine Phantomspeisung gibt. Mit dem Multimeter ließen sich um die 24 V Wechselspannung mit 50 Hz messen, also spricht nichts dagegen, auch mal das Oszi anzuklemmen. Im Ruhezustand bestätigt das Oszi in etwa das, was das Multimeter gemessen hat: Ein 50 Hz-Rechteck-Signal mit etwa 26 V Amplitude und 64 % Duty-Cycle: <gallery> ecl_bus_idle.png | Signalverlauf des ECL-Bus im Ruhezustand </gallery> Drückt man oft genug auf Run/Stop erwischt man auch mal ein bisschen mehr Gezappel als die 50 Hz: <gallery> ecl_bus_transmit.png | ecl_bus_timing.png | </gallery> Mit ein bisschen mehr Zoom lassen sich auch die mutmaßlichen Bitdauern messen - 2,06 ms für 5 Zustandswechsel ergibt 412 µs / "Bit". Mutmaßlich und in Anführungszeichen, da noch nicht bekannt sind, wie genau die Daten übertragen werden. Ist man mit der Run/Stop-Taste geduldiger als mit dem Einstellen eines cleveren Triggers, bekommt man irgendwann folgendes auf den Schirm: <gallery> ecl_bus_receive.png | ecl_bus_receive_frame.png | ecl_bus_receive_timing.png | </gallery> Das sieht doch schon eher nach vollständiger Nachricht aus. Auffällig ist zudem, dass die Pegel der Kommunikation ein Stück niedriger sind als in den Screenshots weiter oben (und zum 50 Hz-Rechteck). Das könnte ein Unterschied zwischen den Teilnehmern sein: Angenommen das zuvor gezeigte Signal ist vom ECL 300, dann ist es naheliegend, dass die selbe Schaltung Versorgung (Erzeugung der 50 Hz) wie zur Kommunikation verwendet wird. Ein Busteilnehmer, insbesondere wenn dieser über den Bus gespeist wird, hat eine andere (tendenziell niedrigere) Spannung, mit der der Bus getrieben werden kann. Beim Blick auf ein Frame auch wieder eine Messung der mutmaßlichen Bitlänge: 3,3 ms für 8 Übergänge = 412,5 µs / "Bit", also sehr nah am Wert von oben. ==Bitübertragung== Aufzeichnungen vom Oszilloskop sind etwas dröge in Sachen Protokoll-Reverse-Engineering - zumindest, wenn man es auch mit einem Logic-Analyzer machen kann. Als Schnittstelle zum LA dient (wie bereits vorher erfolgreich getestet) ein einfacher Optokoppler mit passenden Vorwiderständen. Neben den üblichen Aufzeichnungen mit verschiedenen Aktionen am Gerät lief die Aufzeichnungen auch einfach mal für 10 Minuten ohne besondere Aktivität. Mit ein bisschen Excel-Datenschubserei purzelten zwei Histogramme über die Häufigkeit der verschiedenen Zustandsdauern heraus: <gallery> ecl_bus_bitlenhisto1.png | Histogramm über alle Bitlängen ecl_bus_bitlenhisto2.png | Histogramm über Bitlängen bis 1 ms ecl_bus_bitlenhisto3.png | Histogramm mit besonderer X-Achse </gallery> Zu berücksichtigen ist, dass Low- und High-Zustände gleich dargestellt sind. Im ersten Diagramm sieht man halbwegs gut, dass die Zustände um 7,2 ms und 12,8 ms weitaus am häufigsten eingenommen werden (hier sollte die Kombination aus logarithmischer Skala und Clustergröße 0,001 ms im Hinterkopf behalten werden). In der Summe der beiden Zahlen findet man die Periodendauer der 50 Hz der Versorgung wieder. Schaut man sich einen deutlich kleineren Wertebereich (zweites Diagramm) an sieht man, dass sich bei 0,4-nochwas und 0,8-nochwas Millisekunden mit etwas Phantasie [[wpde:Normalverteilung|normalverteilte Kurven]] ergeben. Dass die zweite "Glocke" bei doppelte Zustandsdauer der ersten hat ist kein Zufall, wählt man bei für die X-Achse ein Intervall von 0,412 ms, sieht man schön die vorher mit dem Oszilloskop bestimmten mutmaßlichen Bitlängen. Woher die Häufungen bei "+0,5" (also 1,5-, 3,5-, ...-facher) Bitlängen herkommt, kann man anhand der Datenlage nicht pauschal sagen; hier hilft ein genauerer Blick in die Aufzeichnung: <gallery> ecl_bus_unknown_timings.png </gallery> An der Stelle hatte ich direkt das Glück, zwei solcher "+0,5"-Bitlängen zu erwischen. Wie es scheint ist das einfach ein wenig Padding hinter den eigentlichen Daten. Aber zu den Daten selbst - scrollt man durch die Aufzeichnung sieht man, dass die Frames immer in Rudeln von 5 kommen: <gallery> ecl_bus_packets.png | Zwei Nachrichten ecl_bus_message.png | Eine Nachricht im Detail </gallery> Nimmt man aus dem zweiten Screenshot die einzelnen Frames und legt sie in Bildbearbeitung übereinander, bekommt man sowas ähnliches wie ein Augendiagramm, das ein bisschen bekannt vorkommt: <gallery> ecl_bus_frames_overlay.png | Alle Frames einer Nachricht überlagert </gallery> erstes Bit immer low, letztes Bit immer low, riecht nach UART - allerdings mit etwas ungewöhnlichen 16 Bit Symbollänge. Die vorhin bestimmten etwa 412 µs Bitlänge entspricht etwa 2400 Baud, den Analyzer in Logic damit gefüttert ergibt Daten: <gallery> ecl_bus_message_decoded.png | Eine Nachricht </gallery> Exportiert man die Daten des Analyzers, bekommt man neben sehr vielen <code>0x0000</code> auch zum Beispiel folgendes: <pre>Zeit Daten ... 20,25630025 0x0000 20,27630175 0x60EF 20,29630150 0x1915 20,31630525 0x0CA8 20,33631175 0x0023 20,35631150 0x0D54 20,37631200 0x0000 20,39631075 0x60EF 20,41631625 0x1952 20,43631700 0x6000 20,45631275 0x0045 20,47631425 0x0D5F 20,49632000 0x0000 ... </pre> Zu beachten ist, dass - wie bei UART üblich - das LSB zuerst kommt. Natürlich war ich anfangs nicht so clever und habe ein Python-Script (basierend auf meinem alten C-Code) zum Analysieren der rohen Aufzeichnungen gebastelt. Das Script ist im Abschnitt Downloads zu finden. Dieses kann die Daten wie folgt ausspucken: <pre>12.956395 0x04AF 0x0B1A 0x0000 0x0000 0x0DD8 19.236316 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 20.276302 0x60EF 0x1915 0x0CA8 0x0023 0x0D54 20.396311 0x60EF 0x1952 0x6000 0x0045 0x0D5F 24.036128 0x01F0 0x0A1E 0x22FA 0x0000 0x0D35 25.635993 0x02F0 0x1512 0x030B 0x6779 0x0D07 41.754978 0x04AF 0x0B11 0x0000 0x0000 0x0DCF 42.054995 0x09AF 0x0005 0x0000 0x0000 0x0DBD 42.194992 0x09FA 0xFF0F 0xFFFF 0x00F0 0x0DFF 48.034069 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 49.073926 0x60EF 0x1921 0x0CAB 0x0023 0x0D63 49.193916 0x60EF 0x194B 0x6000 0x0045 0x0D58 52.833398 0x01F0 0x0A1D 0x22FA 0x0000 0x0D34 54.433216 0x02F0 0x152F 0x030B 0x6779 0x0D24 </pre> =Protokoll= Die übliche Vorgehensweise beim Reverse Engineering eines Protokolls ist, bekannte Informationen zu erkennen bzw. zu erzeugen und wiederzufinden. Aufgrund der zurückliegenden Untersuchung des Protokolls kann diese Phase stark abgekürzt werden - das Rad muss schließlich nicht jedes Mal neu erfunden werden. Wer den alten Artikel kennt oder parallel geöffnet hat, wird vermutlich schon erkannt haben, dass die [[wpde:Byte-Reihenfolge|Byte-Reihenfolge]] der Frames unterschiedlich ist. Um ehrlich zu sein: das ist mir damals nicht wirklich aufgefallen, da der Sprung von roher Datenanalyse zum Interpretieren (im AVR) sehr kurz war. Durch die Nichtbeachtung der Endianness bei der Erfassung, Verarbeitung und Ausgabe ging der Punkt einfach verloren. Auch ein Grund, sich nochmal damit auseinanderzusetzen. ==Header== Schaut man sich im letzten Abschnitt den Auszug das Beispiel genauer an, sieht man zumindest im ersten Symbol (bzw. Word) der Daten eine gewisse Wiederholung. Ein einfacher Trick um einen beschränkten Datenraum zu finden ist die Funktion "Duplikate entfernen" in Excel, nachdem die Symbole in Spalten aufgeteilt sind. Während den verschiedenen Aufzeichnungen ließen sich 11 unterschiedliche Nachrichtentypen identifizieren. Hierbei beinhaltet das niederwertige Byte des ersten Word Sender und Empfänger der Nachricht - das höherwertige Nibble ist der Sender, das niederwertige der Empfänger: {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || ECA 60 |- | E || ECA 86 |- | F || ECL 300 |} Höherwertige Byte des ersten Word entspricht dem Nachrichtentyp: {| class="wikitable sortable" |- ! d[0] !! Typ !! Sender !! Empfänger !! Bezeichnung !! Häufigkeit |- | <code>0x04AF</code> || 04 || A || F || Innentemperatur (ECA 60) || 125/h |- | <code>0x05AF</code> || 05 || A || F || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || - |- | <code>0x09AF</code> || 09 || A || F || Abfrage Tagesprogramm || 63/h |- | <code>0x11AF</code> || 11 || A || F || Zeit setzen || - |- | <code>0x60EF</code> || 60 || E || F || Temperaturfühler ECA 86 || 125/h |- | <code>0x01F0</code> || 01 || F || 0 || Außentemperatur || 125/h |- | <code>0x02F0</code> || 02 || F || 0 || Aktuelle Zeit || 125/h |- | <code>0x05FA</code> || 05 || F || A || Solltemperatur am ECL 300 setzen || - |- | <code>0x06FA</code> || 06 || F || A || Bestätigung Setzen Solltemperatur (Antwort auf 05AF) || - |- | <code>0x09FA</code> || 09 || F || A || Tagesprogramm (Antwort auf 06AF) || 63/h |- | <code>0x62FE</code> || 62 || F || E || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine einstündige Datenerfassung, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. ==Prüfsumme== Das höherwertige Byte im letzten Word habe ich immer mit 0x0D beobachtet, das niederwertige Byte ist eine Prüfsumme, die sich als Summe aller Bytes des Headers und der Nutzdaten berechnet: <source lang="javascript"> var data = [ 0x0100, 0x0302, 0x0504, 0x0706, 0x091C ]; var checksum_calc = 0; var checksum_msg = data[4] & 0xFF; for(var i = 0; i < 4; i++) { checksum_calc += (data[i] >> 8) & 0xFF; checksum_calc += (data[i] >> 0) & 0xFF; } checksum_calc &= 0xFF; console.log("calculated checksum: 0x%s, explected 0x%s", checksum_calc.toString(16), checksum_msg.toString(16) ) </source> Wie man darauf kommt fragt ihr? Ausprobieren und ein bisschen Glück. Die "low hanging fruits" sind in Summe, XOR und CRC - bei letzterem kommt allerdings die Schwierigkeit, dass man den passenden Startwert und Polynom finden muss. Bei CRC-8 sind das theoretisch 65536 Kombinationen (wobei für das Polynom auf bestimmte Werte eingeschränkt werden kann). Wird CRC-16 (oder höhere) verwendet, wird die Anzahl der möglichen Kombinationen deutlich größer. ==Payload== Die 3 Words "in der Mitte" sind die eigentlichen Nutzdaten Die Positionsangaben (d[x]) beziehen sich auf dem 0-basierten Index des Words im Paket, die Angabe "Word x" ist ebenfalls 0-basiert. Beispiel: [[Datei:ecl_bus_message_sample.png]] <code> <span style="color: lightgrey"> 04 AF </span> 0B 1A 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 00001011 00011010 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?!!!!!!! !!!!!!!! 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> In der ersten Zeile sind die Werte der Bytes Hexadezimal dargestellt (Little Endian), das zuerst übertragene Word befindet sich links. Die zweite Zeile beinhaltet die binäre Entsprechung des obigen Wertes. Vergleicht man diese Zeile mit dem oben dargestellten Signal auf der Busleitung, ist jedes Word rückwärts abgebildet (LSB first auf dem Bus, MSB first im Text) Die dritte Zeile stellt die "Bekanntheit" des jeweiligen Bits dar: *!: Bedeutung bekannt *?: Bedeutung unbekannt *0: immer low *1: immer high ===04AF: Innentemperatur=== Diese Nachricht überträgt die am ECA 60 gemessene Temperatur an das ECL 300, wo es als Führungsgröße verwendet werden kann <code> <span style="color: lightgrey"> 04 AF </span> <span class="hb1"> 0B 1A </span> 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 0<span class="hb1">0001011 00011010</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?<span class="hb1">!!!!!!! !!!!!!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:0</span></code> || Innentemperatur || x / 128 || 0x0B1A || 22.2<s>03125</s> °C |} Die theoretische Auflösung der Temperatur beträgt 7,8 m°C, wobei der Wert sicher nicht die Genauigkeit hat. Eine Nachkommastelle reicht. Negative Werte werden vermutlich über das aktuell mit ? markierte MSB im Zweierkomplement, was noch bestätigt werden muss. ===05AF/05FA: Solltemperatur, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit)=== *0x05AF: Solltemperatur am ECA 60 setzen, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) *0x05FA: Solltemperatur am ECL 300 setzen <code> <span style="color: lightgrey"> 05 AF </span> <span class="hb1"> 2C </span> FF <span class="hb2"> 0C </span> 24 <span class="hb3"> </span> 82<span class="hb4"> </span> <span class="hb5"> 00 </span> <span style="color: lightgrey"> 0D 91 </span> <span style="color: lightgrey">00000101 10101111</span> 00<span class="hb1">10110</span>0 11111111 0<span class="hb2">000110</span>0 00100100 <span class="hb3">1</span>0000<span class="hb4">010</span> <span class="hb5">0000000</span>0 <span style="color: lightgrey">00001101 10010001</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00<span class="hb1">!!!!!</span>0 ???????? !<span class="hb2">!!!!!!</span>0 ???????? <span class="hb3">!</span>0000<span class="hb4">!!!</span> <span class="hb5">!!!!!!!</span>0 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.13:9</span></code> || Soll-Temperatur || x || 0x16 || 22 °C |- | <code><span class="hb2">2.14:9</span></code> || Abweichende Temperatur (Entspannen) || (s. u.) || 0x06 || +6 °C |- | <code><span class="hb3">3.15</span></code> || Abweichung aktiv || s. u. || 0x01 || aktiv |- | <code><span class="hb4">3.10:8</span></code> || Betriebsmodus || s. u. || || 2 = Konstante Komforttemperatur |- | <code><span class="hb5">3.7:1</span></code> || Abweichende Temperatur (Abwesenheit) || (s. u.) || 0x00 || 0 °C |} Achtung: hier gibt es noch eine kleine Unsicherheit, was <code>1.7:0</code> macht und wie es zu <code><span class="hb1">1.13:9</span></code> steht. ====Abweichende Temperatur==== In den Words <code><span class="hb2">2.14:9</span></code> und <code><span class="hb5">3.7:1</span></code> sind die Abweichungen zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gelten. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - im Byte um ein Bit nach links verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement beachtet werden. Um vorzeichenbehaftete 8 Bit Integer verwenden zu können, werden im Code die folgenden Bits ersetzt: <source lang="C"> if(type == ECL_DIFF_RELAX) { ecl_data.tmp_diff = (buff[2] >> 9) & 0x7F; if(ecl_data.tmp_diff & 0x20) { ecl_data.tmp_diff |= 0xC0; } } else if(type == ECL_DIFF_AWAY) { ecl_data.tmp_diff = (buff[3] >> 1) & 0x7F; if(ecl_data.tmp_diff & 0x40) { ecl_data.tmp_diff |= 0x80; } } </source> Das Setzen von Abweichungen ist etwas merkwürdig: Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und Wiederverbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEPROM des ECA 60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5 °C bei Abwesenheit oder -10 °C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern. ====Betriebsmodus==== {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Manuell |- | 001 || 1 || Zeitgesteuerter Betrieb |- | 010 || 2 || Konstante Komforttemperatur |- | 011 || 3 || Konstante reduzierte Temperatur |- | 100 || 4 || Standby |} Die restlichen zustände sind mir nicht bekannt. ===06AF/06FA: Bestätigung Setzen Solltemperatur (Antwort auf 05AF)=== Diese Nachricht dient offenbar der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (06FA folgt auf 05AF bw. 06AF folgt auf 05FA) direkt nach einem 05**-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden. ===09AF: Abfrage Tagesprogramm=== Abfrage des Tagesprogrammes für den Heizkreis durch ECA 60. <code> <span style="color: lightgrey"> 09 AF </span> 00 04<span class="hb1"> </span> 00 00 00 00 <span style="color: lightgrey"> 0D BC </span> <span style="color: lightgrey">00001001 10101111</span> 00000000 00000<span class="hb1">100</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 10111100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00000000 00000<span class="hb1">!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.2:0</span></code> || Wochentag || 0=Montag ... 7=Sonntag || 0x04 || Freitag |} Die Ermittlung des Wochentags ist eigentlich klare Sache, aber der Vollständigkeit halber: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Montag |- | 001 || 1 || Dienstag |- | 010 || 2 || Mittwoch |- | 011 || 3 || Donnerstag |- | 100 || 4 || Freitag |- | 101 || 5 || Samstag |- | 110 || 6 || Sonntag |} ===09FA: Rückmeldung Tagesprogramm=== Rückmeldung des Heizkreis-Tagesprogrammes auf Abfrage in 09AF. <code> <span style="color: lightgrey"> 09 FA </span> <span class="hb1"> FF 3F 81 FF 00 FE </span> <span style="color: lightgrey"> 0D BF </span> <span style="color: lightgrey">00001001 11111010</span> <span class="hb1">11111111 00111111 10000001 11111111 00000000 11111110</span> <span style="color: lightgrey">00001101 10111111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:3.0</span></code> || Tagesprogramm als Bitmap || s. u. || s. u. |} Hier habe ich echte Zweifel bekommen, ob die Endianness richtig ist. Um kurz die Fakten zu nennen: Jedes Bit entspricht eine halbe Stunde, in dem Beispiel gibt es zwei Heizphasen: [[Datei:ecl_tagesprogramm.jpg]] also: *04:30 - 08:30 *11:30 - 23:00 Um die Bitmap intuitiver zu bekommen, ist es am einfachsten, die Endianness zu ändern - so wird aus dem Beispiel von oben: <code> <span class="hb1"> 0xFF3F </span><span class="hb2"> 0x81FF </span><span class="hb3"> 0x00FE </span> LE: <span class="hb1">1111111100111111</span><span class="hb2">1000000111111111</span><span class="hb3">0000000011111110</span> BE: <span class="hb1">0011111111111111</span><span class="hb2">1111111110000001</span><span class="hb3">1111111000000000</span> </code> So wird schon eher ein Schuh draus: rechts ist 00:00, links 24:00 - das deckt sich mit der Darstellung oben. ===11AF/02F0: Zeit setzen/aktuelle Zeit=== <code> <span style="color: lightgrey"> 11 AF </span> <span class="hb1"> 03 </span> <span class="hb2"> 20 </span> <span class="hb3"> 05 </span> <span class="hb4"> 0D </span> <span class="hb5"> 7</span><span class="hb6">9 </span> <span class="hb7"> 79 </span> <span style="color: lightgrey"> 0D E7 </span> <span style="color: lightgrey">00010001 10101111</span> 0<span class="hb1">0000011</span> 0<span class="hb2">0100000</span> 00<span class="hb3">000101</span> 00<span class="hb4">001101</span> 0<span class="hb5">111</span><span class="hb6">1001</span> <span class="hb7">01111001</span> <span style="color: lightgrey">00001101 11100111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 0<span class="hb1">!!!!!!!</span> 0<span class="hb2">!!!!!!!</span> 00<span class="hb3">!!!!!!</span> 00<span class="hb4">!!!!!!</span> ?<span class="hb5">!!!</span><span class="hb6">!!!!</span> <span class="hb7">!!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:8</span></code> || Minuten || x || 0x03 || 3 |- | <code><span class="hb2">1.6:0</span></code> || Sekunden || x || 0x20 || 32 |- | <code><span class="hb3">2.13:8</span></code> || Tag || x || 0x05 || 5 |- | <code><span class="hb4">2.5:0</span></code> || Stunden || x || 0x0D || 13 |- | <code><span class="hb5">3.15:12</span></code> || Wochentag || 1=Montag ... 7=Sonntag || 0x07 || Sonntag |- | <code><span class="hb6">3.11:8</span></code> || Monat || x || 0x09 || 9 |- | <code><span class="hb7">3.7:0</span></code> || Jahr || 1900 + x || 0x79 || 2021 |} In dieser Nachricht wird also Sonntag, 2021-09-05 13:03:32 als aktuelles Datum & Zeit gesetzt. Die Sekunden können zumindest am ECA 60 nicht eingestellt werden. Bemerkenswert ist hier, dass bei dieser Nachricht der Wochentag nicht wie in Nachricht 0x09AF nicht bei 0, sondern bei 1 beginnt. Eine Vermutung könnte sein, dass ein Wert von "0" die ECL 300 veranlasst, den Wochentag selbst zu berechnen, was ich jedoch nicht beobachten konnte. Wieder der Vollständigkeit halber hier die Lookup-Tabelle der Wochentage: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 001 || 1 || Montag |- | 010 || 2 || Dienstag |- | 011 || 3 || Mittwoch |- | 100 || 4 || Donnerstag |- | 101 || 5 || Freitag |- | 110 || 6 || Samstag |- | 111 || 7 || Sonntag |} ===60EF: Temperaturfühler ECA 86=== Mit dieser Nachricht werden die vom ECA 86 gemessenen Temperaturen übertragen. Das Modul verfügt über 4 Sensoreingänge, die Übertragung der Messwerte erfolgt in zwei Nachrichten. <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1E DB </span> <span class="hb2"> 0B 96 </span> 00 <span class="hb3"> 2</span><span class="hb4">3 </span> <span style="color: lightgrey"> 0D 0C </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011110 11011011</span> <span class="hb2">00001011 10010110</span> 00000000 <span class="hb3">0010</span><span class="hb4">0011</span> <span style="color: lightgrey">00001101 00001100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> <span class="hb2">!!!!!!!! !!!!!!!!</span> 00000000 <span class="hb3">!!!!</span><span class="hb4">!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1EDB || 61,7<s>109375</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x0B96 || 23,1<s>71875</s> °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x02 || 2 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x03 || 3 |} Für die zweite Gruppe sieht die Nachricht wie folgt aus: <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1F 2F </span> <span class="hb2"> 60 00 </span> 00 <span class="hb3"> 4</span><span class="hb4">5 </span> <span style="color: lightgrey"> 0D 42 </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011111 00101111</span> <span class="hb2">01100000 00000000</span> 00000000 <span class="hb3">0100</span><span class="hb4">0101</span> <span style="color: lightgrey">00001101 01000010</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1F2F || 62,3<s>671875</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x6000 || 192 °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x04 || 4 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x05 || 5 |} Index 1 und 2 konnten noch nicht beobachtet werden, Index 5 entspricht dem ungenutzten Eingang 4, der mit einem Widerstand terminiert ist. Dementsprechend ist davon auszugehen, dass die Indizes einfach um 2 verschoben sind. ===01F0: Außentemperatur=== <code> <span style="color: lightgrey"> 01 F0 </span> <span class="hb1"> 0A 06 </span> <span class="hb2"> 2</span>2 <span class="hb3"> </span> FA 00 00 <span style="color: lightgrey"> 0D 1D </span> <span style="color: lightgrey">00000001 11110000</span> <span class="hb1">00001010 00000110</span> 00<span class="hb2">10</span>00<span class="hb3">10</span> 11111010 00000000 00000000 <span style="color: lightgrey">00001101 00011101</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> ??<span class="hb2">!!</span>??<span class="hb3">!!</span> ???????? 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Außentemperatur || x / 128 || 0x0A06 || 20,0<s>46875</s> °C |- | <code><span class="hb2">2.13:12</span></code> || Betriebsmodus Brauchwasserkreis || s. u. || 0x02 || Komforttemperatur |- | <code><span class="hb3">2.9:8</span></code> || Betriebsmodus Heizkreis || s. u. || 0x02 || Komforttemperatur |} Der Betriebsmodus wird vermutlich nach folgender Tabelle bestimmt: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Reduzierte Temperatur |- | 01 || 1 || Optimierte Aufheizphase |- | 10 || 2 || Komforttemperatur |- | 11 || 3 || Optimierte Absenkphase |} Bisher habe ich nur Modus 0 und 2 gesehen, die anderen beiden stammen aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet. ===62FE: Setzen Relais an ECA 86=== <code> <span style="color: lightgrey"> 62 FE </span> FF FF FF FF 00 00 <span style="color: lightgrey"> 0D 5C </span> <span style="color: lightgrey">01100010 11111110</span> 11111111 11111111 11111111 11111111 00000000 00000000 <span style="color: lightgrey">00001101 01011100</span> </code> Da die Heizung während der Aufzeichnungen nie aktiv war, gibt es hierzu noch keine Informationen. ===Alarmmodul=== Das Alarmmodul ist leider nicht am ECL Bus (sondern am ECL 300) angeschlossen, auch konnte ich keine Nachrichten ausmachen, in dem ein etwaiger Alarmzustand übertragen wird. Dadurch ist die Ferndiagnose über den ECL-Bus leider in weite Ferne gerückt. =Downloads= *[[Datei:Ecl_bus_data.zip]] Aufzeichnungen (Saleae Logic 2.3.35), gefilterte, und gesparste Daten und Python-Scripts zum Filtern/Parsen. Bitte beachten: Die Aufzeichnungen in Logic sind invertiert 99965ad225b17b4804435ee953e9d3cacafa3165 1691 1690 2021-09-07T11:41:28Z Chris 2 /* 09FA: Rückmeldung Tagesprogramm */ Bild verkleinert wikitext text/x-wiki Neue Erfahrungen bringen neue Sichtweisen. Unter dieser Prämisse - und nachdem ich den Artikel des [[ECL-Bus-Decoder]]s selbst nicht mehr ganz verstanden habe - entschied ich mich, das Ganze nochmal anzuschauen. Worum geht es? Bei der Heizungsanlage meiner Eltern - genauer einer Grundwasser-Wärmepumpe - ist ein Regler von Danfoss verbaut. Genauer ein ECL 300. Dieser verwendet zur Kommunikation mit seinen externen Modulen den so genannten ECL-Bus, der zwar in der Anleitung erwähnt, aber keine weiteren Details genannt werden. Auch der Support von Danfoss schwieg sich bei einer Anfrage vor einigen Jahren darüber (und die RS-232-Schnittstelle an der Front des ECL 300) aus: "Es gibt keine Dokumentation". Oder vielmehr: Es gibt keine Dokumentation, die für die Öffentlichkeit bestimmt ist. "Kein Problem, dann mach ich halt eine" war mein Gedanke damals, woraufhin der oben genannte Artikel entstand. =Busteilnehmer= Lt. meiner Recherchen gibt/gab es folgende Geräte für das System (untersuchte sind fett markiert): * '''ECL 300''': elektronischer Temperaturregler (ECL 301 ist die 24 V-Version) * '''ECA 60''': Raumleitgerät mit Temperaturmessung * ECA 62: Raumleitgerät mit Temperatur- und Luftfeuchtemessung * ECA 61/63: Im Prinzip wie ECA 60/62, nur werden diese als "Remote control" statt "Room panels" bezeichnet * '''ECA 86''': Temperatur-Alarm- & Relaismodul für ECL 30x (4x Temperatur, 2x Relais) ==ECL 300== [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Der/Die/Das ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. ==ECA 86== [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt. ==ECA 60== [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEPROM 93C66A (512x8 bit) gespeichert. Auf der Rückseite des Gerätes befindet sich ein Schalter zum Wählen der Adresse (A und B), ein Umschalten auf B bezweckt lediglich, dass das Raumleitgerät ewig im Init-Zustand (keine Anzeige von Messwerten) bleibt. =Einbaumodule= Ferner bin ich über folgende Einsteckmodule für die ECL 30x gestoßen: * ECA 71: Modbus-Adapter für die ECL 30x * ECA 81: RS-232-Adapter für die ECL 30x * ECA 87: RS-232-Datenlogger In der Anleitung des ECA 81 wird gleich auf der ersten Seite darauf hingewiesen ''"Es ist kein Protokoll für die ECA 81 RS 232 Kommunikation vorhanden. ECA 81 dient nur der Kommunikation mit der DAnfoss ECL Comfort Service Software."'' Die Anleitung des ECA 87 beinhaltet die Information, dass die Einsteckmodule (u. a.?) über SPI kommunizieren - und immerhin ist das Protokoll dafür beschrieben. Am Frontpanel der ECL 30x befindet sich allerdings schon eine RS-232-Schnittstelle, die allerdings ein anderes Protokoll spricht. In dem Sinne: Danke für nichts. =Schnittstelle= Wie eingangs angedeutet, gibt es nicht sonderlich viele öffentlich verfügbare Informationen über die Schnittstelle. Aus der Installationsanleitung lässt sich allerdings drauf schließen, dass es ein eindrahtiges Bus-System ist: Am Regler ist Klemme 15 mit "BUS" gekennzeichnet, Klemme 16 mit GND (an der auch die Temperaturfühler terminiert sind). ==Physischer Layer== Da die Raumleitgeräte keine eigene Versorgung haben ist ferner anzunehmen, dass es eine Phantomspeisung gibt. Mit dem Multimeter ließen sich um die 24 V Wechselspannung mit 50 Hz messen, also spricht nichts dagegen, auch mal das Oszi anzuklemmen. Im Ruhezustand bestätigt das Oszi in etwa das, was das Multimeter gemessen hat: Ein 50 Hz-Rechteck-Signal mit etwa 26 V Amplitude und 64 % Duty-Cycle: <gallery> ecl_bus_idle.png | Signalverlauf des ECL-Bus im Ruhezustand </gallery> Drückt man oft genug auf Run/Stop erwischt man auch mal ein bisschen mehr Gezappel als die 50 Hz: <gallery> ecl_bus_transmit.png | ecl_bus_timing.png | </gallery> Mit ein bisschen mehr Zoom lassen sich auch die mutmaßlichen Bitdauern messen - 2,06 ms für 5 Zustandswechsel ergibt 412 µs / "Bit". Mutmaßlich und in Anführungszeichen, da noch nicht bekannt sind, wie genau die Daten übertragen werden. Ist man mit der Run/Stop-Taste geduldiger als mit dem Einstellen eines cleveren Triggers, bekommt man irgendwann folgendes auf den Schirm: <gallery> ecl_bus_receive.png | ecl_bus_receive_frame.png | ecl_bus_receive_timing.png | </gallery> Das sieht doch schon eher nach vollständiger Nachricht aus. Auffällig ist zudem, dass die Pegel der Kommunikation ein Stück niedriger sind als in den Screenshots weiter oben (und zum 50 Hz-Rechteck). Das könnte ein Unterschied zwischen den Teilnehmern sein: Angenommen das zuvor gezeigte Signal ist vom ECL 300, dann ist es naheliegend, dass die selbe Schaltung Versorgung (Erzeugung der 50 Hz) wie zur Kommunikation verwendet wird. Ein Busteilnehmer, insbesondere wenn dieser über den Bus gespeist wird, hat eine andere (tendenziell niedrigere) Spannung, mit der der Bus getrieben werden kann. Beim Blick auf ein Frame auch wieder eine Messung der mutmaßlichen Bitlänge: 3,3 ms für 8 Übergänge = 412,5 µs / "Bit", also sehr nah am Wert von oben. ==Bitübertragung== Aufzeichnungen vom Oszilloskop sind etwas dröge in Sachen Protokoll-Reverse-Engineering - zumindest, wenn man es auch mit einem Logic-Analyzer machen kann. Als Schnittstelle zum LA dient (wie bereits vorher erfolgreich getestet) ein einfacher Optokoppler mit passenden Vorwiderständen. Neben den üblichen Aufzeichnungen mit verschiedenen Aktionen am Gerät lief die Aufzeichnungen auch einfach mal für 10 Minuten ohne besondere Aktivität. Mit ein bisschen Excel-Datenschubserei purzelten zwei Histogramme über die Häufigkeit der verschiedenen Zustandsdauern heraus: <gallery> ecl_bus_bitlenhisto1.png | Histogramm über alle Bitlängen ecl_bus_bitlenhisto2.png | Histogramm über Bitlängen bis 1 ms ecl_bus_bitlenhisto3.png | Histogramm mit besonderer X-Achse </gallery> Zu berücksichtigen ist, dass Low- und High-Zustände gleich dargestellt sind. Im ersten Diagramm sieht man halbwegs gut, dass die Zustände um 7,2 ms und 12,8 ms weitaus am häufigsten eingenommen werden (hier sollte die Kombination aus logarithmischer Skala und Clustergröße 0,001 ms im Hinterkopf behalten werden). In der Summe der beiden Zahlen findet man die Periodendauer der 50 Hz der Versorgung wieder. Schaut man sich einen deutlich kleineren Wertebereich (zweites Diagramm) an sieht man, dass sich bei 0,4-nochwas und 0,8-nochwas Millisekunden mit etwas Phantasie [[wpde:Normalverteilung|normalverteilte Kurven]] ergeben. Dass die zweite "Glocke" bei doppelte Zustandsdauer der ersten hat ist kein Zufall, wählt man bei für die X-Achse ein Intervall von 0,412 ms, sieht man schön die vorher mit dem Oszilloskop bestimmten mutmaßlichen Bitlängen. Woher die Häufungen bei "+0,5" (also 1,5-, 3,5-, ...-facher) Bitlängen herkommt, kann man anhand der Datenlage nicht pauschal sagen; hier hilft ein genauerer Blick in die Aufzeichnung: <gallery> ecl_bus_unknown_timings.png </gallery> An der Stelle hatte ich direkt das Glück, zwei solcher "+0,5"-Bitlängen zu erwischen. Wie es scheint ist das einfach ein wenig Padding hinter den eigentlichen Daten. Aber zu den Daten selbst - scrollt man durch die Aufzeichnung sieht man, dass die Frames immer in Rudeln von 5 kommen: <gallery> ecl_bus_packets.png | Zwei Nachrichten ecl_bus_message.png | Eine Nachricht im Detail </gallery> Nimmt man aus dem zweiten Screenshot die einzelnen Frames und legt sie in Bildbearbeitung übereinander, bekommt man sowas ähnliches wie ein Augendiagramm, das ein bisschen bekannt vorkommt: <gallery> ecl_bus_frames_overlay.png | Alle Frames einer Nachricht überlagert </gallery> erstes Bit immer low, letztes Bit immer low, riecht nach UART - allerdings mit etwas ungewöhnlichen 16 Bit Symbollänge. Die vorhin bestimmten etwa 412 µs Bitlänge entspricht etwa 2400 Baud, den Analyzer in Logic damit gefüttert ergibt Daten: <gallery> ecl_bus_message_decoded.png | Eine Nachricht </gallery> Exportiert man die Daten des Analyzers, bekommt man neben sehr vielen <code>0x0000</code> auch zum Beispiel folgendes: <pre>Zeit Daten ... 20,25630025 0x0000 20,27630175 0x60EF 20,29630150 0x1915 20,31630525 0x0CA8 20,33631175 0x0023 20,35631150 0x0D54 20,37631200 0x0000 20,39631075 0x60EF 20,41631625 0x1952 20,43631700 0x6000 20,45631275 0x0045 20,47631425 0x0D5F 20,49632000 0x0000 ... </pre> Zu beachten ist, dass - wie bei UART üblich - das LSB zuerst kommt. Natürlich war ich anfangs nicht so clever und habe ein Python-Script (basierend auf meinem alten C-Code) zum Analysieren der rohen Aufzeichnungen gebastelt. Das Script ist im Abschnitt Downloads zu finden. Dieses kann die Daten wie folgt ausspucken: <pre>12.956395 0x04AF 0x0B1A 0x0000 0x0000 0x0DD8 19.236316 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 20.276302 0x60EF 0x1915 0x0CA8 0x0023 0x0D54 20.396311 0x60EF 0x1952 0x6000 0x0045 0x0D5F 24.036128 0x01F0 0x0A1E 0x22FA 0x0000 0x0D35 25.635993 0x02F0 0x1512 0x030B 0x6779 0x0D07 41.754978 0x04AF 0x0B11 0x0000 0x0000 0x0DCF 42.054995 0x09AF 0x0005 0x0000 0x0000 0x0DBD 42.194992 0x09FA 0xFF0F 0xFFFF 0x00F0 0x0DFF 48.034069 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 49.073926 0x60EF 0x1921 0x0CAB 0x0023 0x0D63 49.193916 0x60EF 0x194B 0x6000 0x0045 0x0D58 52.833398 0x01F0 0x0A1D 0x22FA 0x0000 0x0D34 54.433216 0x02F0 0x152F 0x030B 0x6779 0x0D24 </pre> =Protokoll= Die übliche Vorgehensweise beim Reverse Engineering eines Protokolls ist, bekannte Informationen zu erkennen bzw. zu erzeugen und wiederzufinden. Aufgrund der zurückliegenden Untersuchung des Protokolls kann diese Phase stark abgekürzt werden - das Rad muss schließlich nicht jedes Mal neu erfunden werden. Wer den alten Artikel kennt oder parallel geöffnet hat, wird vermutlich schon erkannt haben, dass die [[wpde:Byte-Reihenfolge|Byte-Reihenfolge]] der Frames unterschiedlich ist. Um ehrlich zu sein: das ist mir damals nicht wirklich aufgefallen, da der Sprung von roher Datenanalyse zum Interpretieren (im AVR) sehr kurz war. Durch die Nichtbeachtung der Endianness bei der Erfassung, Verarbeitung und Ausgabe ging der Punkt einfach verloren. Auch ein Grund, sich nochmal damit auseinanderzusetzen. ==Header== Schaut man sich im letzten Abschnitt den Auszug das Beispiel genauer an, sieht man zumindest im ersten Symbol (bzw. Word) der Daten eine gewisse Wiederholung. Ein einfacher Trick um einen beschränkten Datenraum zu finden ist die Funktion "Duplikate entfernen" in Excel, nachdem die Symbole in Spalten aufgeteilt sind. Während den verschiedenen Aufzeichnungen ließen sich 11 unterschiedliche Nachrichtentypen identifizieren. Hierbei beinhaltet das niederwertige Byte des ersten Word Sender und Empfänger der Nachricht - das höherwertige Nibble ist der Sender, das niederwertige der Empfänger: {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || ECA 60 |- | E || ECA 86 |- | F || ECL 300 |} Höherwertige Byte des ersten Word entspricht dem Nachrichtentyp: {| class="wikitable sortable" |- ! d[0] !! Typ !! Sender !! Empfänger !! Bezeichnung !! Häufigkeit |- | <code>0x04AF</code> || 04 || A || F || Innentemperatur (ECA 60) || 125/h |- | <code>0x05AF</code> || 05 || A || F || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || - |- | <code>0x09AF</code> || 09 || A || F || Abfrage Tagesprogramm || 63/h |- | <code>0x11AF</code> || 11 || A || F || Zeit setzen || - |- | <code>0x60EF</code> || 60 || E || F || Temperaturfühler ECA 86 || 125/h |- | <code>0x01F0</code> || 01 || F || 0 || Außentemperatur || 125/h |- | <code>0x02F0</code> || 02 || F || 0 || Aktuelle Zeit || 125/h |- | <code>0x05FA</code> || 05 || F || A || Solltemperatur am ECL 300 setzen || - |- | <code>0x06FA</code> || 06 || F || A || Bestätigung Setzen Solltemperatur (Antwort auf 05AF) || - |- | <code>0x09FA</code> || 09 || F || A || Tagesprogramm (Antwort auf 06AF) || 63/h |- | <code>0x62FE</code> || 62 || F || E || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine einstündige Datenerfassung, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. ==Prüfsumme== Das höherwertige Byte im letzten Word habe ich immer mit 0x0D beobachtet, das niederwertige Byte ist eine Prüfsumme, die sich als Summe aller Bytes des Headers und der Nutzdaten berechnet: <source lang="javascript"> var data = [ 0x0100, 0x0302, 0x0504, 0x0706, 0x091C ]; var checksum_calc = 0; var checksum_msg = data[4] & 0xFF; for(var i = 0; i < 4; i++) { checksum_calc += (data[i] >> 8) & 0xFF; checksum_calc += (data[i] >> 0) & 0xFF; } checksum_calc &= 0xFF; console.log("calculated checksum: 0x%s, explected 0x%s", checksum_calc.toString(16), checksum_msg.toString(16) ) </source> Wie man darauf kommt fragt ihr? Ausprobieren und ein bisschen Glück. Die "low hanging fruits" sind in Summe, XOR und CRC - bei letzterem kommt allerdings die Schwierigkeit, dass man den passenden Startwert und Polynom finden muss. Bei CRC-8 sind das theoretisch 65536 Kombinationen (wobei für das Polynom auf bestimmte Werte eingeschränkt werden kann). Wird CRC-16 (oder höhere) verwendet, wird die Anzahl der möglichen Kombinationen deutlich größer. ==Payload== Die 3 Words "in der Mitte" sind die eigentlichen Nutzdaten Die Positionsangaben (d[x]) beziehen sich auf dem 0-basierten Index des Words im Paket, die Angabe "Word x" ist ebenfalls 0-basiert. Beispiel: [[Datei:ecl_bus_message_sample.png]] <code> <span style="color: lightgrey"> 04 AF </span> 0B 1A 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 00001011 00011010 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?!!!!!!! !!!!!!!! 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> In der ersten Zeile sind die Werte der Bytes Hexadezimal dargestellt (Little Endian), das zuerst übertragene Word befindet sich links. Die zweite Zeile beinhaltet die binäre Entsprechung des obigen Wertes. Vergleicht man diese Zeile mit dem oben dargestellten Signal auf der Busleitung, ist jedes Word rückwärts abgebildet (LSB first auf dem Bus, MSB first im Text) Die dritte Zeile stellt die "Bekanntheit" des jeweiligen Bits dar: *!: Bedeutung bekannt *?: Bedeutung unbekannt *0: immer low *1: immer high ===04AF: Innentemperatur=== Diese Nachricht überträgt die am ECA 60 gemessene Temperatur an das ECL 300, wo es als Führungsgröße verwendet werden kann <code> <span style="color: lightgrey"> 04 AF </span> <span class="hb1"> 0B 1A </span> 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 0<span class="hb1">0001011 00011010</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?<span class="hb1">!!!!!!! !!!!!!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:0</span></code> || Innentemperatur || x / 128 || 0x0B1A || 22.2<s>03125</s> °C |} Die theoretische Auflösung der Temperatur beträgt 7,8 m°C, wobei der Wert sicher nicht die Genauigkeit hat. Eine Nachkommastelle reicht. Negative Werte werden vermutlich über das aktuell mit ? markierte MSB im Zweierkomplement, was noch bestätigt werden muss. ===05AF/05FA: Solltemperatur, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit)=== *0x05AF: Solltemperatur am ECA 60 setzen, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) *0x05FA: Solltemperatur am ECL 300 setzen <code> <span style="color: lightgrey"> 05 AF </span> <span class="hb1"> 2C </span> FF <span class="hb2"> 0C </span> 24 <span class="hb3"> </span> 82<span class="hb4"> </span> <span class="hb5"> 00 </span> <span style="color: lightgrey"> 0D 91 </span> <span style="color: lightgrey">00000101 10101111</span> 00<span class="hb1">10110</span>0 11111111 0<span class="hb2">000110</span>0 00100100 <span class="hb3">1</span>0000<span class="hb4">010</span> <span class="hb5">0000000</span>0 <span style="color: lightgrey">00001101 10010001</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00<span class="hb1">!!!!!</span>0 ???????? !<span class="hb2">!!!!!!</span>0 ???????? <span class="hb3">!</span>0000<span class="hb4">!!!</span> <span class="hb5">!!!!!!!</span>0 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.13:9</span></code> || Soll-Temperatur || x || 0x16 || 22 °C |- | <code><span class="hb2">2.14:9</span></code> || Abweichende Temperatur (Entspannen) || (s. u.) || 0x06 || +6 °C |- | <code><span class="hb3">3.15</span></code> || Abweichung aktiv || s. u. || 0x01 || aktiv |- | <code><span class="hb4">3.10:8</span></code> || Betriebsmodus || s. u. || || 2 = Konstante Komforttemperatur |- | <code><span class="hb5">3.7:1</span></code> || Abweichende Temperatur (Abwesenheit) || (s. u.) || 0x00 || 0 °C |} Achtung: hier gibt es noch eine kleine Unsicherheit, was <code>1.7:0</code> macht und wie es zu <code><span class="hb1">1.13:9</span></code> steht. ====Abweichende Temperatur==== In den Words <code><span class="hb2">2.14:9</span></code> und <code><span class="hb5">3.7:1</span></code> sind die Abweichungen zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gelten. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - im Byte um ein Bit nach links verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement beachtet werden. Um vorzeichenbehaftete 8 Bit Integer verwenden zu können, werden im Code die folgenden Bits ersetzt: <source lang="C"> if(type == ECL_DIFF_RELAX) { ecl_data.tmp_diff = (buff[2] >> 9) & 0x7F; if(ecl_data.tmp_diff & 0x20) { ecl_data.tmp_diff |= 0xC0; } } else if(type == ECL_DIFF_AWAY) { ecl_data.tmp_diff = (buff[3] >> 1) & 0x7F; if(ecl_data.tmp_diff & 0x40) { ecl_data.tmp_diff |= 0x80; } } </source> Das Setzen von Abweichungen ist etwas merkwürdig: Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und Wiederverbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEPROM des ECA 60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5 °C bei Abwesenheit oder -10 °C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern. ====Betriebsmodus==== {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Manuell |- | 001 || 1 || Zeitgesteuerter Betrieb |- | 010 || 2 || Konstante Komforttemperatur |- | 011 || 3 || Konstante reduzierte Temperatur |- | 100 || 4 || Standby |} Die restlichen zustände sind mir nicht bekannt. ===06AF/06FA: Bestätigung Setzen Solltemperatur (Antwort auf 05AF)=== Diese Nachricht dient offenbar der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (06FA folgt auf 05AF bw. 06AF folgt auf 05FA) direkt nach einem 05**-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden. ===09AF: Abfrage Tagesprogramm=== Abfrage des Tagesprogrammes für den Heizkreis durch ECA 60. <code> <span style="color: lightgrey"> 09 AF </span> 00 04<span class="hb1"> </span> 00 00 00 00 <span style="color: lightgrey"> 0D BC </span> <span style="color: lightgrey">00001001 10101111</span> 00000000 00000<span class="hb1">100</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 10111100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00000000 00000<span class="hb1">!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.2:0</span></code> || Wochentag || 0=Montag ... 7=Sonntag || 0x04 || Freitag |} Die Ermittlung des Wochentags ist eigentlich klare Sache, aber der Vollständigkeit halber: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Montag |- | 001 || 1 || Dienstag |- | 010 || 2 || Mittwoch |- | 011 || 3 || Donnerstag |- | 100 || 4 || Freitag |- | 101 || 5 || Samstag |- | 110 || 6 || Sonntag |} ===09FA: Rückmeldung Tagesprogramm=== Rückmeldung des Heizkreis-Tagesprogrammes auf Abfrage in 09AF. <code> <span style="color: lightgrey"> 09 FA </span> <span class="hb1"> FF 3F 81 FF 00 FE </span> <span style="color: lightgrey"> 0D BF </span> <span style="color: lightgrey">00001001 11111010</span> <span class="hb1">11111111 00111111 10000001 11111111 00000000 11111110</span> <span style="color: lightgrey">00001101 10111111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:3.0</span></code> || Tagesprogramm als Bitmap || s. u. || s. u. |} Hier habe ich echte Zweifel bekommen, ob die Endianness richtig ist. Um kurz die Fakten zu nennen: Jedes Bit entspricht eine halbe Stunde, in dem Beispiel gibt es zwei Heizphasen: [[Datei:ecl_tagesprogramm.jpg|300px]] also: *04:30 - 08:30 *11:30 - 23:00 Um die Bitmap intuitiver zu bekommen, ist es am einfachsten, die Endianness zu ändern - so wird aus dem Beispiel von oben: <code> <span class="hb1"> 0xFF3F </span><span class="hb2"> 0x81FF </span><span class="hb3"> 0x00FE </span> LE: <span class="hb1">1111111100111111</span><span class="hb2">1000000111111111</span><span class="hb3">0000000011111110</span> BE: <span class="hb1">0011111111111111</span><span class="hb2">1111111110000001</span><span class="hb3">1111111000000000</span> </code> So wird schon eher ein Schuh draus: rechts ist 00:00, links 24:00 - das deckt sich mit der Darstellung oben. ===11AF/02F0: Zeit setzen/aktuelle Zeit=== <code> <span style="color: lightgrey"> 11 AF </span> <span class="hb1"> 03 </span> <span class="hb2"> 20 </span> <span class="hb3"> 05 </span> <span class="hb4"> 0D </span> <span class="hb5"> 7</span><span class="hb6">9 </span> <span class="hb7"> 79 </span> <span style="color: lightgrey"> 0D E7 </span> <span style="color: lightgrey">00010001 10101111</span> 0<span class="hb1">0000011</span> 0<span class="hb2">0100000</span> 00<span class="hb3">000101</span> 00<span class="hb4">001101</span> 0<span class="hb5">111</span><span class="hb6">1001</span> <span class="hb7">01111001</span> <span style="color: lightgrey">00001101 11100111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 0<span class="hb1">!!!!!!!</span> 0<span class="hb2">!!!!!!!</span> 00<span class="hb3">!!!!!!</span> 00<span class="hb4">!!!!!!</span> ?<span class="hb5">!!!</span><span class="hb6">!!!!</span> <span class="hb7">!!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:8</span></code> || Minuten || x || 0x03 || 3 |- | <code><span class="hb2">1.6:0</span></code> || Sekunden || x || 0x20 || 32 |- | <code><span class="hb3">2.13:8</span></code> || Tag || x || 0x05 || 5 |- | <code><span class="hb4">2.5:0</span></code> || Stunden || x || 0x0D || 13 |- | <code><span class="hb5">3.15:12</span></code> || Wochentag || 1=Montag ... 7=Sonntag || 0x07 || Sonntag |- | <code><span class="hb6">3.11:8</span></code> || Monat || x || 0x09 || 9 |- | <code><span class="hb7">3.7:0</span></code> || Jahr || 1900 + x || 0x79 || 2021 |} In dieser Nachricht wird also Sonntag, 2021-09-05 13:03:32 als aktuelles Datum & Zeit gesetzt. Die Sekunden können zumindest am ECA 60 nicht eingestellt werden. Bemerkenswert ist hier, dass bei dieser Nachricht der Wochentag nicht wie in Nachricht 0x09AF nicht bei 0, sondern bei 1 beginnt. Eine Vermutung könnte sein, dass ein Wert von "0" die ECL 300 veranlasst, den Wochentag selbst zu berechnen, was ich jedoch nicht beobachten konnte. Wieder der Vollständigkeit halber hier die Lookup-Tabelle der Wochentage: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 001 || 1 || Montag |- | 010 || 2 || Dienstag |- | 011 || 3 || Mittwoch |- | 100 || 4 || Donnerstag |- | 101 || 5 || Freitag |- | 110 || 6 || Samstag |- | 111 || 7 || Sonntag |} ===60EF: Temperaturfühler ECA 86=== Mit dieser Nachricht werden die vom ECA 86 gemessenen Temperaturen übertragen. Das Modul verfügt über 4 Sensoreingänge, die Übertragung der Messwerte erfolgt in zwei Nachrichten. <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1E DB </span> <span class="hb2"> 0B 96 </span> 00 <span class="hb3"> 2</span><span class="hb4">3 </span> <span style="color: lightgrey"> 0D 0C </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011110 11011011</span> <span class="hb2">00001011 10010110</span> 00000000 <span class="hb3">0010</span><span class="hb4">0011</span> <span style="color: lightgrey">00001101 00001100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> <span class="hb2">!!!!!!!! !!!!!!!!</span> 00000000 <span class="hb3">!!!!</span><span class="hb4">!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1EDB || 61,7<s>109375</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x0B96 || 23,1<s>71875</s> °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x02 || 2 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x03 || 3 |} Für die zweite Gruppe sieht die Nachricht wie folgt aus: <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1F 2F </span> <span class="hb2"> 60 00 </span> 00 <span class="hb3"> 4</span><span class="hb4">5 </span> <span style="color: lightgrey"> 0D 42 </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011111 00101111</span> <span class="hb2">01100000 00000000</span> 00000000 <span class="hb3">0100</span><span class="hb4">0101</span> <span style="color: lightgrey">00001101 01000010</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1F2F || 62,3<s>671875</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x6000 || 192 °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x04 || 4 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x05 || 5 |} Index 1 und 2 konnten noch nicht beobachtet werden, Index 5 entspricht dem ungenutzten Eingang 4, der mit einem Widerstand terminiert ist. Dementsprechend ist davon auszugehen, dass die Indizes einfach um 2 verschoben sind. ===01F0: Außentemperatur=== <code> <span style="color: lightgrey"> 01 F0 </span> <span class="hb1"> 0A 06 </span> <span class="hb2"> 2</span>2 <span class="hb3"> </span> FA 00 00 <span style="color: lightgrey"> 0D 1D </span> <span style="color: lightgrey">00000001 11110000</span> <span class="hb1">00001010 00000110</span> 00<span class="hb2">10</span>00<span class="hb3">10</span> 11111010 00000000 00000000 <span style="color: lightgrey">00001101 00011101</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> ??<span class="hb2">!!</span>??<span class="hb3">!!</span> ???????? 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Außentemperatur || x / 128 || 0x0A06 || 20,0<s>46875</s> °C |- | <code><span class="hb2">2.13:12</span></code> || Betriebsmodus Brauchwasserkreis || s. u. || 0x02 || Komforttemperatur |- | <code><span class="hb3">2.9:8</span></code> || Betriebsmodus Heizkreis || s. u. || 0x02 || Komforttemperatur |} Der Betriebsmodus wird vermutlich nach folgender Tabelle bestimmt: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Reduzierte Temperatur |- | 01 || 1 || Optimierte Aufheizphase |- | 10 || 2 || Komforttemperatur |- | 11 || 3 || Optimierte Absenkphase |} Bisher habe ich nur Modus 0 und 2 gesehen, die anderen beiden stammen aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet. ===62FE: Setzen Relais an ECA 86=== <code> <span style="color: lightgrey"> 62 FE </span> FF FF FF FF 00 00 <span style="color: lightgrey"> 0D 5C </span> <span style="color: lightgrey">01100010 11111110</span> 11111111 11111111 11111111 11111111 00000000 00000000 <span style="color: lightgrey">00001101 01011100</span> </code> Da die Heizung während der Aufzeichnungen nie aktiv war, gibt es hierzu noch keine Informationen. ===Alarmmodul=== Das Alarmmodul ist leider nicht am ECL Bus (sondern am ECL 300) angeschlossen, auch konnte ich keine Nachrichten ausmachen, in dem ein etwaiger Alarmzustand übertragen wird. Dadurch ist die Ferndiagnose über den ECL-Bus leider in weite Ferne gerückt. =Downloads= *[[Datei:Ecl_bus_data.zip]] Aufzeichnungen (Saleae Logic 2.3.35), gefilterte, und gesparste Daten und Python-Scripts zum Filtern/Parsen. Bitte beachten: Die Aufzeichnungen in Logic sind invertiert 3df8ded6fa085d0a6fb4ef7587f347cbb421632a 1693 1691 2021-09-07T11:44:53Z Chris 2 /* Abweichende Temperatur */ Zeichensetzung wikitext text/x-wiki Neue Erfahrungen bringen neue Sichtweisen. Unter dieser Prämisse - und nachdem ich den Artikel des [[ECL-Bus-Decoder]]s selbst nicht mehr ganz verstanden habe - entschied ich mich, das Ganze nochmal anzuschauen. Worum geht es? Bei der Heizungsanlage meiner Eltern - genauer einer Grundwasser-Wärmepumpe - ist ein Regler von Danfoss verbaut. Genauer ein ECL 300. Dieser verwendet zur Kommunikation mit seinen externen Modulen den so genannten ECL-Bus, der zwar in der Anleitung erwähnt, aber keine weiteren Details genannt werden. Auch der Support von Danfoss schwieg sich bei einer Anfrage vor einigen Jahren darüber (und die RS-232-Schnittstelle an der Front des ECL 300) aus: "Es gibt keine Dokumentation". Oder vielmehr: Es gibt keine Dokumentation, die für die Öffentlichkeit bestimmt ist. "Kein Problem, dann mach ich halt eine" war mein Gedanke damals, woraufhin der oben genannte Artikel entstand. =Busteilnehmer= Lt. meiner Recherchen gibt/gab es folgende Geräte für das System (untersuchte sind fett markiert): * '''ECL 300''': elektronischer Temperaturregler (ECL 301 ist die 24 V-Version) * '''ECA 60''': Raumleitgerät mit Temperaturmessung * ECA 62: Raumleitgerät mit Temperatur- und Luftfeuchtemessung * ECA 61/63: Im Prinzip wie ECA 60/62, nur werden diese als "Remote control" statt "Room panels" bezeichnet * '''ECA 86''': Temperatur-Alarm- & Relaismodul für ECL 30x (4x Temperatur, 2x Relais) ==ECL 300== [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Der/Die/Das ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. ==ECA 86== [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt. ==ECA 60== [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEPROM 93C66A (512x8 bit) gespeichert. Auf der Rückseite des Gerätes befindet sich ein Schalter zum Wählen der Adresse (A und B), ein Umschalten auf B bezweckt lediglich, dass das Raumleitgerät ewig im Init-Zustand (keine Anzeige von Messwerten) bleibt. =Einbaumodule= Ferner bin ich über folgende Einsteckmodule für die ECL 30x gestoßen: * ECA 71: Modbus-Adapter für die ECL 30x * ECA 81: RS-232-Adapter für die ECL 30x * ECA 87: RS-232-Datenlogger In der Anleitung des ECA 81 wird gleich auf der ersten Seite darauf hingewiesen ''"Es ist kein Protokoll für die ECA 81 RS 232 Kommunikation vorhanden. ECA 81 dient nur der Kommunikation mit der DAnfoss ECL Comfort Service Software."'' Die Anleitung des ECA 87 beinhaltet die Information, dass die Einsteckmodule (u. a.?) über SPI kommunizieren - und immerhin ist das Protokoll dafür beschrieben. Am Frontpanel der ECL 30x befindet sich allerdings schon eine RS-232-Schnittstelle, die allerdings ein anderes Protokoll spricht. In dem Sinne: Danke für nichts. =Schnittstelle= Wie eingangs angedeutet, gibt es nicht sonderlich viele öffentlich verfügbare Informationen über die Schnittstelle. Aus der Installationsanleitung lässt sich allerdings drauf schließen, dass es ein eindrahtiges Bus-System ist: Am Regler ist Klemme 15 mit "BUS" gekennzeichnet, Klemme 16 mit GND (an der auch die Temperaturfühler terminiert sind). ==Physischer Layer== Da die Raumleitgeräte keine eigene Versorgung haben ist ferner anzunehmen, dass es eine Phantomspeisung gibt. Mit dem Multimeter ließen sich um die 24 V Wechselspannung mit 50 Hz messen, also spricht nichts dagegen, auch mal das Oszi anzuklemmen. Im Ruhezustand bestätigt das Oszi in etwa das, was das Multimeter gemessen hat: Ein 50 Hz-Rechteck-Signal mit etwa 26 V Amplitude und 64 % Duty-Cycle: <gallery> ecl_bus_idle.png | Signalverlauf des ECL-Bus im Ruhezustand </gallery> Drückt man oft genug auf Run/Stop erwischt man auch mal ein bisschen mehr Gezappel als die 50 Hz: <gallery> ecl_bus_transmit.png | ecl_bus_timing.png | </gallery> Mit ein bisschen mehr Zoom lassen sich auch die mutmaßlichen Bitdauern messen - 2,06 ms für 5 Zustandswechsel ergibt 412 µs / "Bit". Mutmaßlich und in Anführungszeichen, da noch nicht bekannt sind, wie genau die Daten übertragen werden. Ist man mit der Run/Stop-Taste geduldiger als mit dem Einstellen eines cleveren Triggers, bekommt man irgendwann folgendes auf den Schirm: <gallery> ecl_bus_receive.png | ecl_bus_receive_frame.png | ecl_bus_receive_timing.png | </gallery> Das sieht doch schon eher nach vollständiger Nachricht aus. Auffällig ist zudem, dass die Pegel der Kommunikation ein Stück niedriger sind als in den Screenshots weiter oben (und zum 50 Hz-Rechteck). Das könnte ein Unterschied zwischen den Teilnehmern sein: Angenommen das zuvor gezeigte Signal ist vom ECL 300, dann ist es naheliegend, dass die selbe Schaltung Versorgung (Erzeugung der 50 Hz) wie zur Kommunikation verwendet wird. Ein Busteilnehmer, insbesondere wenn dieser über den Bus gespeist wird, hat eine andere (tendenziell niedrigere) Spannung, mit der der Bus getrieben werden kann. Beim Blick auf ein Frame auch wieder eine Messung der mutmaßlichen Bitlänge: 3,3 ms für 8 Übergänge = 412,5 µs / "Bit", also sehr nah am Wert von oben. ==Bitübertragung== Aufzeichnungen vom Oszilloskop sind etwas dröge in Sachen Protokoll-Reverse-Engineering - zumindest, wenn man es auch mit einem Logic-Analyzer machen kann. Als Schnittstelle zum LA dient (wie bereits vorher erfolgreich getestet) ein einfacher Optokoppler mit passenden Vorwiderständen. Neben den üblichen Aufzeichnungen mit verschiedenen Aktionen am Gerät lief die Aufzeichnungen auch einfach mal für 10 Minuten ohne besondere Aktivität. Mit ein bisschen Excel-Datenschubserei purzelten zwei Histogramme über die Häufigkeit der verschiedenen Zustandsdauern heraus: <gallery> ecl_bus_bitlenhisto1.png | Histogramm über alle Bitlängen ecl_bus_bitlenhisto2.png | Histogramm über Bitlängen bis 1 ms ecl_bus_bitlenhisto3.png | Histogramm mit besonderer X-Achse </gallery> Zu berücksichtigen ist, dass Low- und High-Zustände gleich dargestellt sind. Im ersten Diagramm sieht man halbwegs gut, dass die Zustände um 7,2 ms und 12,8 ms weitaus am häufigsten eingenommen werden (hier sollte die Kombination aus logarithmischer Skala und Clustergröße 0,001 ms im Hinterkopf behalten werden). In der Summe der beiden Zahlen findet man die Periodendauer der 50 Hz der Versorgung wieder. Schaut man sich einen deutlich kleineren Wertebereich (zweites Diagramm) an sieht man, dass sich bei 0,4-nochwas und 0,8-nochwas Millisekunden mit etwas Phantasie [[wpde:Normalverteilung|normalverteilte Kurven]] ergeben. Dass die zweite "Glocke" bei doppelte Zustandsdauer der ersten hat ist kein Zufall, wählt man bei für die X-Achse ein Intervall von 0,412 ms, sieht man schön die vorher mit dem Oszilloskop bestimmten mutmaßlichen Bitlängen. Woher die Häufungen bei "+0,5" (also 1,5-, 3,5-, ...-facher) Bitlängen herkommt, kann man anhand der Datenlage nicht pauschal sagen; hier hilft ein genauerer Blick in die Aufzeichnung: <gallery> ecl_bus_unknown_timings.png </gallery> An der Stelle hatte ich direkt das Glück, zwei solcher "+0,5"-Bitlängen zu erwischen. Wie es scheint ist das einfach ein wenig Padding hinter den eigentlichen Daten. Aber zu den Daten selbst - scrollt man durch die Aufzeichnung sieht man, dass die Frames immer in Rudeln von 5 kommen: <gallery> ecl_bus_packets.png | Zwei Nachrichten ecl_bus_message.png | Eine Nachricht im Detail </gallery> Nimmt man aus dem zweiten Screenshot die einzelnen Frames und legt sie in Bildbearbeitung übereinander, bekommt man sowas ähnliches wie ein Augendiagramm, das ein bisschen bekannt vorkommt: <gallery> ecl_bus_frames_overlay.png | Alle Frames einer Nachricht überlagert </gallery> erstes Bit immer low, letztes Bit immer low, riecht nach UART - allerdings mit etwas ungewöhnlichen 16 Bit Symbollänge. Die vorhin bestimmten etwa 412 µs Bitlänge entspricht etwa 2400 Baud, den Analyzer in Logic damit gefüttert ergibt Daten: <gallery> ecl_bus_message_decoded.png | Eine Nachricht </gallery> Exportiert man die Daten des Analyzers, bekommt man neben sehr vielen <code>0x0000</code> auch zum Beispiel folgendes: <pre>Zeit Daten ... 20,25630025 0x0000 20,27630175 0x60EF 20,29630150 0x1915 20,31630525 0x0CA8 20,33631175 0x0023 20,35631150 0x0D54 20,37631200 0x0000 20,39631075 0x60EF 20,41631625 0x1952 20,43631700 0x6000 20,45631275 0x0045 20,47631425 0x0D5F 20,49632000 0x0000 ... </pre> Zu beachten ist, dass - wie bei UART üblich - das LSB zuerst kommt. Natürlich war ich anfangs nicht so clever und habe ein Python-Script (basierend auf meinem alten C-Code) zum Analysieren der rohen Aufzeichnungen gebastelt. Das Script ist im Abschnitt Downloads zu finden. Dieses kann die Daten wie folgt ausspucken: <pre>12.956395 0x04AF 0x0B1A 0x0000 0x0000 0x0DD8 19.236316 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 20.276302 0x60EF 0x1915 0x0CA8 0x0023 0x0D54 20.396311 0x60EF 0x1952 0x6000 0x0045 0x0D5F 24.036128 0x01F0 0x0A1E 0x22FA 0x0000 0x0D35 25.635993 0x02F0 0x1512 0x030B 0x6779 0x0D07 41.754978 0x04AF 0x0B11 0x0000 0x0000 0x0DCF 42.054995 0x09AF 0x0005 0x0000 0x0000 0x0DBD 42.194992 0x09FA 0xFF0F 0xFFFF 0x00F0 0x0DFF 48.034069 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 49.073926 0x60EF 0x1921 0x0CAB 0x0023 0x0D63 49.193916 0x60EF 0x194B 0x6000 0x0045 0x0D58 52.833398 0x01F0 0x0A1D 0x22FA 0x0000 0x0D34 54.433216 0x02F0 0x152F 0x030B 0x6779 0x0D24 </pre> =Protokoll= Die übliche Vorgehensweise beim Reverse Engineering eines Protokolls ist, bekannte Informationen zu erkennen bzw. zu erzeugen und wiederzufinden. Aufgrund der zurückliegenden Untersuchung des Protokolls kann diese Phase stark abgekürzt werden - das Rad muss schließlich nicht jedes Mal neu erfunden werden. Wer den alten Artikel kennt oder parallel geöffnet hat, wird vermutlich schon erkannt haben, dass die [[wpde:Byte-Reihenfolge|Byte-Reihenfolge]] der Frames unterschiedlich ist. Um ehrlich zu sein: das ist mir damals nicht wirklich aufgefallen, da der Sprung von roher Datenanalyse zum Interpretieren (im AVR) sehr kurz war. Durch die Nichtbeachtung der Endianness bei der Erfassung, Verarbeitung und Ausgabe ging der Punkt einfach verloren. Auch ein Grund, sich nochmal damit auseinanderzusetzen. ==Header== Schaut man sich im letzten Abschnitt den Auszug das Beispiel genauer an, sieht man zumindest im ersten Symbol (bzw. Word) der Daten eine gewisse Wiederholung. Ein einfacher Trick um einen beschränkten Datenraum zu finden ist die Funktion "Duplikate entfernen" in Excel, nachdem die Symbole in Spalten aufgeteilt sind. Während den verschiedenen Aufzeichnungen ließen sich 11 unterschiedliche Nachrichtentypen identifizieren. Hierbei beinhaltet das niederwertige Byte des ersten Word Sender und Empfänger der Nachricht - das höherwertige Nibble ist der Sender, das niederwertige der Empfänger: {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || ECA 60 |- | E || ECA 86 |- | F || ECL 300 |} Höherwertige Byte des ersten Word entspricht dem Nachrichtentyp: {| class="wikitable sortable" |- ! d[0] !! Typ !! Sender !! Empfänger !! Bezeichnung !! Häufigkeit |- | <code>0x04AF</code> || 04 || A || F || Innentemperatur (ECA 60) || 125/h |- | <code>0x05AF</code> || 05 || A || F || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || - |- | <code>0x09AF</code> || 09 || A || F || Abfrage Tagesprogramm || 63/h |- | <code>0x11AF</code> || 11 || A || F || Zeit setzen || - |- | <code>0x60EF</code> || 60 || E || F || Temperaturfühler ECA 86 || 125/h |- | <code>0x01F0</code> || 01 || F || 0 || Außentemperatur || 125/h |- | <code>0x02F0</code> || 02 || F || 0 || Aktuelle Zeit || 125/h |- | <code>0x05FA</code> || 05 || F || A || Solltemperatur am ECL 300 setzen || - |- | <code>0x06FA</code> || 06 || F || A || Bestätigung Setzen Solltemperatur (Antwort auf 05AF) || - |- | <code>0x09FA</code> || 09 || F || A || Tagesprogramm (Antwort auf 06AF) || 63/h |- | <code>0x62FE</code> || 62 || F || E || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine einstündige Datenerfassung, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. ==Prüfsumme== Das höherwertige Byte im letzten Word habe ich immer mit 0x0D beobachtet, das niederwertige Byte ist eine Prüfsumme, die sich als Summe aller Bytes des Headers und der Nutzdaten berechnet: <source lang="javascript"> var data = [ 0x0100, 0x0302, 0x0504, 0x0706, 0x091C ]; var checksum_calc = 0; var checksum_msg = data[4] & 0xFF; for(var i = 0; i < 4; i++) { checksum_calc += (data[i] >> 8) & 0xFF; checksum_calc += (data[i] >> 0) & 0xFF; } checksum_calc &= 0xFF; console.log("calculated checksum: 0x%s, explected 0x%s", checksum_calc.toString(16), checksum_msg.toString(16) ) </source> Wie man darauf kommt fragt ihr? Ausprobieren und ein bisschen Glück. Die "low hanging fruits" sind in Summe, XOR und CRC - bei letzterem kommt allerdings die Schwierigkeit, dass man den passenden Startwert und Polynom finden muss. Bei CRC-8 sind das theoretisch 65536 Kombinationen (wobei für das Polynom auf bestimmte Werte eingeschränkt werden kann). Wird CRC-16 (oder höhere) verwendet, wird die Anzahl der möglichen Kombinationen deutlich größer. ==Payload== Die 3 Words "in der Mitte" sind die eigentlichen Nutzdaten Die Positionsangaben (d[x]) beziehen sich auf dem 0-basierten Index des Words im Paket, die Angabe "Word x" ist ebenfalls 0-basiert. Beispiel: [[Datei:ecl_bus_message_sample.png]] <code> <span style="color: lightgrey"> 04 AF </span> 0B 1A 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 00001011 00011010 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?!!!!!!! !!!!!!!! 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> In der ersten Zeile sind die Werte der Bytes Hexadezimal dargestellt (Little Endian), das zuerst übertragene Word befindet sich links. Die zweite Zeile beinhaltet die binäre Entsprechung des obigen Wertes. Vergleicht man diese Zeile mit dem oben dargestellten Signal auf der Busleitung, ist jedes Word rückwärts abgebildet (LSB first auf dem Bus, MSB first im Text) Die dritte Zeile stellt die "Bekanntheit" des jeweiligen Bits dar: *!: Bedeutung bekannt *?: Bedeutung unbekannt *0: immer low *1: immer high ===04AF: Innentemperatur=== Diese Nachricht überträgt die am ECA 60 gemessene Temperatur an das ECL 300, wo es als Führungsgröße verwendet werden kann <code> <span style="color: lightgrey"> 04 AF </span> <span class="hb1"> 0B 1A </span> 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 0<span class="hb1">0001011 00011010</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?<span class="hb1">!!!!!!! !!!!!!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:0</span></code> || Innentemperatur || x / 128 || 0x0B1A || 22.2<s>03125</s> °C |} Die theoretische Auflösung der Temperatur beträgt 7,8 m°C, wobei der Wert sicher nicht die Genauigkeit hat. Eine Nachkommastelle reicht. Negative Werte werden vermutlich über das aktuell mit ? markierte MSB im Zweierkomplement, was noch bestätigt werden muss. ===05AF/05FA: Solltemperatur, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit)=== *0x05AF: Solltemperatur am ECA 60 setzen, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) *0x05FA: Solltemperatur am ECL 300 setzen <code> <span style="color: lightgrey"> 05 AF </span> <span class="hb1"> 2C </span> FF <span class="hb2"> 0C </span> 24 <span class="hb3"> </span> 82<span class="hb4"> </span> <span class="hb5"> 00 </span> <span style="color: lightgrey"> 0D 91 </span> <span style="color: lightgrey">00000101 10101111</span> 00<span class="hb1">10110</span>0 11111111 0<span class="hb2">000110</span>0 00100100 <span class="hb3">1</span>0000<span class="hb4">010</span> <span class="hb5">0000000</span>0 <span style="color: lightgrey">00001101 10010001</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00<span class="hb1">!!!!!</span>0 ???????? !<span class="hb2">!!!!!!</span>0 ???????? <span class="hb3">!</span>0000<span class="hb4">!!!</span> <span class="hb5">!!!!!!!</span>0 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.13:9</span></code> || Soll-Temperatur || x || 0x16 || 22 °C |- | <code><span class="hb2">2.14:9</span></code> || Abweichende Temperatur (Entspannen) || (s. u.) || 0x06 || +6 °C |- | <code><span class="hb3">3.15</span></code> || Abweichung aktiv || s. u. || 0x01 || aktiv |- | <code><span class="hb4">3.10:8</span></code> || Betriebsmodus || s. u. || || 2 = Konstante Komforttemperatur |- | <code><span class="hb5">3.7:1</span></code> || Abweichende Temperatur (Abwesenheit) || (s. u.) || 0x00 || 0 °C |} Achtung: hier gibt es noch eine kleine Unsicherheit, was <code>1.7:0</code> macht und wie es zu <code><span class="hb1">1.13:9</span></code> steht. ====Abweichende Temperatur==== In den Words <code><span class="hb2">2.14:9</span></code> und <code><span class="hb5">3.7:1</span></code> sind die Abweichungen zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gelten. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - im Byte um ein Bit nach links verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement beachtet werden. Um vorzeichenbehaftete 8 Bit Integer verwenden zu können, werden im Code die folgenden Bits ersetzt: <source lang="C"> if(type == ECL_DIFF_RELAX) { ecl_data.tmp_diff = (buff[2] >> 9) & 0x7F; if(ecl_data.tmp_diff & 0x20) { ecl_data.tmp_diff |= 0xC0; } } else if(type == ECL_DIFF_AWAY) { ecl_data.tmp_diff = (buff[3] >> 1) & 0x7F; if(ecl_data.tmp_diff & 0x40) { ecl_data.tmp_diff |= 0x80; } } </source> Das Setzen von Abweichungen ist etwas merkwürdig: Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und Wiederverbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEPROM des ECA 60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5 °C bei Abwesenheit oder -10 °C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21 °C mit -10 °C (also Solltemperatur 11 °C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern. ====Betriebsmodus==== {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Manuell |- | 001 || 1 || Zeitgesteuerter Betrieb |- | 010 || 2 || Konstante Komforttemperatur |- | 011 || 3 || Konstante reduzierte Temperatur |- | 100 || 4 || Standby |} Die restlichen zustände sind mir nicht bekannt. ===06AF/06FA: Bestätigung Setzen Solltemperatur (Antwort auf 05AF)=== Diese Nachricht dient offenbar der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (06FA folgt auf 05AF bw. 06AF folgt auf 05FA) direkt nach einem 05**-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden. ===09AF: Abfrage Tagesprogramm=== Abfrage des Tagesprogrammes für den Heizkreis durch ECA 60. <code> <span style="color: lightgrey"> 09 AF </span> 00 04<span class="hb1"> </span> 00 00 00 00 <span style="color: lightgrey"> 0D BC </span> <span style="color: lightgrey">00001001 10101111</span> 00000000 00000<span class="hb1">100</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 10111100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00000000 00000<span class="hb1">!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.2:0</span></code> || Wochentag || 0=Montag ... 7=Sonntag || 0x04 || Freitag |} Die Ermittlung des Wochentags ist eigentlich klare Sache, aber der Vollständigkeit halber: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Montag |- | 001 || 1 || Dienstag |- | 010 || 2 || Mittwoch |- | 011 || 3 || Donnerstag |- | 100 || 4 || Freitag |- | 101 || 5 || Samstag |- | 110 || 6 || Sonntag |} ===09FA: Rückmeldung Tagesprogramm=== Rückmeldung des Heizkreis-Tagesprogrammes auf Abfrage in 09AF. <code> <span style="color: lightgrey"> 09 FA </span> <span class="hb1"> FF 3F 81 FF 00 FE </span> <span style="color: lightgrey"> 0D BF </span> <span style="color: lightgrey">00001001 11111010</span> <span class="hb1">11111111 00111111 10000001 11111111 00000000 11111110</span> <span style="color: lightgrey">00001101 10111111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:3.0</span></code> || Tagesprogramm als Bitmap || s. u. || s. u. |} Hier habe ich echte Zweifel bekommen, ob die Endianness richtig ist. Um kurz die Fakten zu nennen: Jedes Bit entspricht eine halbe Stunde, in dem Beispiel gibt es zwei Heizphasen: [[Datei:ecl_tagesprogramm.jpg|300px]] also: *04:30 - 08:30 *11:30 - 23:00 Um die Bitmap intuitiver zu bekommen, ist es am einfachsten, die Endianness zu ändern - so wird aus dem Beispiel von oben: <code> <span class="hb1"> 0xFF3F </span><span class="hb2"> 0x81FF </span><span class="hb3"> 0x00FE </span> LE: <span class="hb1">1111111100111111</span><span class="hb2">1000000111111111</span><span class="hb3">0000000011111110</span> BE: <span class="hb1">0011111111111111</span><span class="hb2">1111111110000001</span><span class="hb3">1111111000000000</span> </code> So wird schon eher ein Schuh draus: rechts ist 00:00, links 24:00 - das deckt sich mit der Darstellung oben. ===11AF/02F0: Zeit setzen/aktuelle Zeit=== <code> <span style="color: lightgrey"> 11 AF </span> <span class="hb1"> 03 </span> <span class="hb2"> 20 </span> <span class="hb3"> 05 </span> <span class="hb4"> 0D </span> <span class="hb5"> 7</span><span class="hb6">9 </span> <span class="hb7"> 79 </span> <span style="color: lightgrey"> 0D E7 </span> <span style="color: lightgrey">00010001 10101111</span> 0<span class="hb1">0000011</span> 0<span class="hb2">0100000</span> 00<span class="hb3">000101</span> 00<span class="hb4">001101</span> 0<span class="hb5">111</span><span class="hb6">1001</span> <span class="hb7">01111001</span> <span style="color: lightgrey">00001101 11100111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 0<span class="hb1">!!!!!!!</span> 0<span class="hb2">!!!!!!!</span> 00<span class="hb3">!!!!!!</span> 00<span class="hb4">!!!!!!</span> ?<span class="hb5">!!!</span><span class="hb6">!!!!</span> <span class="hb7">!!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:8</span></code> || Minuten || x || 0x03 || 3 |- | <code><span class="hb2">1.6:0</span></code> || Sekunden || x || 0x20 || 32 |- | <code><span class="hb3">2.13:8</span></code> || Tag || x || 0x05 || 5 |- | <code><span class="hb4">2.5:0</span></code> || Stunden || x || 0x0D || 13 |- | <code><span class="hb5">3.15:12</span></code> || Wochentag || 1=Montag ... 7=Sonntag || 0x07 || Sonntag |- | <code><span class="hb6">3.11:8</span></code> || Monat || x || 0x09 || 9 |- | <code><span class="hb7">3.7:0</span></code> || Jahr || 1900 + x || 0x79 || 2021 |} In dieser Nachricht wird also Sonntag, 2021-09-05 13:03:32 als aktuelles Datum & Zeit gesetzt. Die Sekunden können zumindest am ECA 60 nicht eingestellt werden. Bemerkenswert ist hier, dass bei dieser Nachricht der Wochentag nicht wie in Nachricht 0x09AF nicht bei 0, sondern bei 1 beginnt. Eine Vermutung könnte sein, dass ein Wert von "0" die ECL 300 veranlasst, den Wochentag selbst zu berechnen, was ich jedoch nicht beobachten konnte. Wieder der Vollständigkeit halber hier die Lookup-Tabelle der Wochentage: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 001 || 1 || Montag |- | 010 || 2 || Dienstag |- | 011 || 3 || Mittwoch |- | 100 || 4 || Donnerstag |- | 101 || 5 || Freitag |- | 110 || 6 || Samstag |- | 111 || 7 || Sonntag |} ===60EF: Temperaturfühler ECA 86=== Mit dieser Nachricht werden die vom ECA 86 gemessenen Temperaturen übertragen. Das Modul verfügt über 4 Sensoreingänge, die Übertragung der Messwerte erfolgt in zwei Nachrichten. <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1E DB </span> <span class="hb2"> 0B 96 </span> 00 <span class="hb3"> 2</span><span class="hb4">3 </span> <span style="color: lightgrey"> 0D 0C </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011110 11011011</span> <span class="hb2">00001011 10010110</span> 00000000 <span class="hb3">0010</span><span class="hb4">0011</span> <span style="color: lightgrey">00001101 00001100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> <span class="hb2">!!!!!!!! !!!!!!!!</span> 00000000 <span class="hb3">!!!!</span><span class="hb4">!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1EDB || 61,7<s>109375</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x0B96 || 23,1<s>71875</s> °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x02 || 2 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x03 || 3 |} Für die zweite Gruppe sieht die Nachricht wie folgt aus: <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1F 2F </span> <span class="hb2"> 60 00 </span> 00 <span class="hb3"> 4</span><span class="hb4">5 </span> <span style="color: lightgrey"> 0D 42 </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011111 00101111</span> <span class="hb2">01100000 00000000</span> 00000000 <span class="hb3">0100</span><span class="hb4">0101</span> <span style="color: lightgrey">00001101 01000010</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1F2F || 62,3<s>671875</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x6000 || 192 °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x04 || 4 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x05 || 5 |} Index 1 und 2 konnten noch nicht beobachtet werden, Index 5 entspricht dem ungenutzten Eingang 4, der mit einem Widerstand terminiert ist. Dementsprechend ist davon auszugehen, dass die Indizes einfach um 2 verschoben sind. ===01F0: Außentemperatur=== <code> <span style="color: lightgrey"> 01 F0 </span> <span class="hb1"> 0A 06 </span> <span class="hb2"> 2</span>2 <span class="hb3"> </span> FA 00 00 <span style="color: lightgrey"> 0D 1D </span> <span style="color: lightgrey">00000001 11110000</span> <span class="hb1">00001010 00000110</span> 00<span class="hb2">10</span>00<span class="hb3">10</span> 11111010 00000000 00000000 <span style="color: lightgrey">00001101 00011101</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> ??<span class="hb2">!!</span>??<span class="hb3">!!</span> ???????? 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Außentemperatur || x / 128 || 0x0A06 || 20,0<s>46875</s> °C |- | <code><span class="hb2">2.13:12</span></code> || Betriebsmodus Brauchwasserkreis || s. u. || 0x02 || Komforttemperatur |- | <code><span class="hb3">2.9:8</span></code> || Betriebsmodus Heizkreis || s. u. || 0x02 || Komforttemperatur |} Der Betriebsmodus wird vermutlich nach folgender Tabelle bestimmt: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Reduzierte Temperatur |- | 01 || 1 || Optimierte Aufheizphase |- | 10 || 2 || Komforttemperatur |- | 11 || 3 || Optimierte Absenkphase |} Bisher habe ich nur Modus 0 und 2 gesehen, die anderen beiden stammen aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet. ===62FE: Setzen Relais an ECA 86=== <code> <span style="color: lightgrey"> 62 FE </span> FF FF FF FF 00 00 <span style="color: lightgrey"> 0D 5C </span> <span style="color: lightgrey">01100010 11111110</span> 11111111 11111111 11111111 11111111 00000000 00000000 <span style="color: lightgrey">00001101 01011100</span> </code> Da die Heizung während der Aufzeichnungen nie aktiv war, gibt es hierzu noch keine Informationen. ===Alarmmodul=== Das Alarmmodul ist leider nicht am ECL Bus (sondern am ECL 300) angeschlossen, auch konnte ich keine Nachrichten ausmachen, in dem ein etwaiger Alarmzustand übertragen wird. Dadurch ist die Ferndiagnose über den ECL-Bus leider in weite Ferne gerückt. =Downloads= *[[Datei:Ecl_bus_data.zip]] Aufzeichnungen (Saleae Logic 2.3.35), gefilterte, und gesparste Daten und Python-Scripts zum Filtern/Parsen. Bitte beachten: Die Aufzeichnungen in Logic sind invertiert a75e169b051b726f72df6e2ba632b1799ac0d641 1696 1693 2021-09-07T11:48:06Z Chris 2 wikitext text/x-wiki Neue Erfahrungen bringen neue Sichtweisen. Unter dieser Prämisse - und nachdem ich den Artikel des [[ECL-Bus-Decoder]]s selbst nicht mehr ganz verstanden habe - entschied ich mich, das Ganze nochmal anzuschauen. Worum geht es? Bei der Heizungsanlage meiner Eltern - genauer einer Grundwasser-Wärmepumpe - ist ein Regler von Danfoss verbaut. Genauer ein ECL 300. Dieser verwendet zur Kommunikation mit seinen externen Modulen den so genannten ECL-Bus, der zwar in der Anleitung erwähnt, aber keine weiteren Details genannt werden. Auch der Support von Danfoss schwieg sich bei einer Anfrage vor einigen Jahren darüber (und die RS-232-Schnittstelle an der Front des ECL 300) aus: "Es gibt keine Dokumentation". Oder vielmehr: Es gibt keine Dokumentation, die für die Öffentlichkeit bestimmt ist. "Kein Problem, dann mach ich halt eine" war mein Gedanke damals, woraufhin der oben genannte Artikel entstand. =Busteilnehmer= Lt. meiner Recherchen gibt/gab es folgende Geräte für das System (untersuchte sind fett markiert): * '''ECL 300''': elektronischer Temperaturregler (ECL 301 ist die 24 V-Version) * '''ECA 60''': Raumleitgerät mit Temperaturmessung * ECA 62: Raumleitgerät mit Temperatur- und Luftfeuchtemessung * ECA 61/63: Im Prinzip wie ECA 60/62, nur werden diese als "Remote control" statt "Room panels" bezeichnet * '''ECA 86''': Temperatur-Alarm- & Relaismodul für ECL 30x (4x Temperatur, 2x Relais) ==ECL 300== [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Der/Die/Das ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. ==ECA 86== [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt. ==ECA 60== [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEPROM 93C66A (512x8 bit) gespeichert. Auf der Rückseite des Gerätes befindet sich ein Schalter zum Wählen der Adresse (A und B), ein Umschalten auf B bezweckt lediglich, dass das Raumleitgerät ewig im Init-Zustand (keine Anzeige von Messwerten) bleibt. =Einbaumodule= Ferner bin ich über folgende Einsteckmodule für die ECL 30x gestoßen: * ECA 71: Modbus-Adapter für die ECL 30x * ECA 81: RS-232-Adapter für die ECL 30x * ECA 87: RS-232-Datenlogger In der Anleitung des ECA 81 wird gleich auf der ersten Seite darauf hingewiesen ''"Es ist kein Protokoll für die ECA 81 RS 232 Kommunikation vorhanden. ECA 81 dient nur der Kommunikation mit der DAnfoss ECL Comfort Service Software."'' Die Anleitung des ECA 87 beinhaltet die Information, dass die Einsteckmodule (u. a.?) über SPI kommunizieren - und immerhin ist das Protokoll dafür beschrieben. Am Frontpanel der ECL 30x befindet sich allerdings schon eine RS-232-Schnittstelle, die allerdings ein anderes Protokoll spricht. In dem Sinne: Danke für nichts. =Schnittstelle= Wie eingangs angedeutet, gibt es nicht sonderlich viele öffentlich verfügbare Informationen über die Schnittstelle. Aus der Installationsanleitung lässt sich allerdings drauf schließen, dass es ein eindrahtiges Bus-System ist: Am Regler ist Klemme 15 mit "BUS" gekennzeichnet, Klemme 16 mit GND (an der auch die Temperaturfühler terminiert sind). ==Physischer Layer== Da die Raumleitgeräte keine eigene Versorgung haben ist ferner anzunehmen, dass es eine Phantomspeisung gibt. Mit dem Multimeter ließen sich um die 24 V Wechselspannung mit 50 Hz messen, also spricht nichts dagegen, auch mal das Oszi anzuklemmen. Im Ruhezustand bestätigt das Oszi in etwa das, was das Multimeter gemessen hat: Ein 50 Hz-Rechteck-Signal mit etwa 26 V Amplitude und 64 % Duty-Cycle: <gallery> ecl_bus_idle.png | Signalverlauf des ECL-Bus im Ruhezustand </gallery> Drückt man oft genug auf Run/Stop erwischt man auch mal ein bisschen mehr Gezappel als die 50 Hz: <gallery> ecl_bus_transmit.png | ecl_bus_timing.png | </gallery> Mit ein bisschen mehr Zoom lassen sich auch die mutmaßlichen Bitdauern messen - 2,06 ms für 5 Zustandswechsel ergibt 412 µs / "Bit". Mutmaßlich und in Anführungszeichen, da noch nicht bekannt sind, wie genau die Daten übertragen werden. Ist man mit der Run/Stop-Taste geduldiger als mit dem Einstellen eines cleveren Triggers, bekommt man irgendwann folgendes auf den Schirm: <gallery> ecl_bus_receive.png | ecl_bus_receive_frame.png | ecl_bus_receive_timing.png | </gallery> Das sieht doch schon eher nach vollständiger Nachricht aus. Auffällig ist zudem, dass die Pegel der Kommunikation ein Stück niedriger sind als in den Screenshots weiter oben (und zum 50 Hz-Rechteck). Das könnte ein Unterschied zwischen den Teilnehmern sein: Angenommen das zuvor gezeigte Signal ist vom ECL 300, dann ist es naheliegend, dass die selbe Schaltung Versorgung (Erzeugung der 50 Hz) wie zur Kommunikation verwendet wird. Ein Busteilnehmer, insbesondere wenn dieser über den Bus gespeist wird, hat eine andere (tendenziell niedrigere) Spannung, mit der der Bus getrieben werden kann. Beim Blick auf ein Frame auch wieder eine Messung der mutmaßlichen Bitlänge: 3,3 ms für 8 Übergänge = 412,5 µs / "Bit", also sehr nah am Wert von oben. ==Bitübertragung== Aufzeichnungen vom Oszilloskop sind etwas dröge in Sachen Protokoll-Reverse-Engineering - zumindest, wenn man es auch mit einem Logic-Analyzer machen kann. Als Schnittstelle zum LA dient (wie bereits vorher erfolgreich getestet) ein einfacher Optokoppler mit passenden Vorwiderständen. Neben den üblichen Aufzeichnungen mit verschiedenen Aktionen am Gerät lief die Aufzeichnungen auch einfach mal für 10 Minuten ohne besondere Aktivität. Mit ein bisschen Excel-Datenschubserei purzelten zwei Histogramme über die Häufigkeit der verschiedenen Zustandsdauern heraus: <gallery> ecl_bus_bitlenhisto1.png | Histogramm über alle Bitlängen ecl_bus_bitlenhisto2.png | Histogramm über Bitlängen bis 1 ms ecl_bus_bitlenhisto3.png | Histogramm mit besonderer X-Achse </gallery> Zu berücksichtigen ist, dass Low- und High-Zustände gleich dargestellt sind. Im ersten Diagramm sieht man halbwegs gut, dass die Zustände um 7,2 ms und 12,8 ms weitaus am häufigsten eingenommen werden (hier sollte die Kombination aus logarithmischer Skala und Clustergröße 0,001 ms im Hinterkopf behalten werden). In der Summe der beiden Zahlen findet man die Periodendauer der 50 Hz der Versorgung wieder. Schaut man sich einen deutlich kleineren Wertebereich (zweites Diagramm) an sieht man, dass sich bei 0,4-nochwas und 0,8-nochwas Millisekunden mit etwas Phantasie [[wpde:Normalverteilung|normalverteilte Kurven]] ergeben. Dass die zweite "Glocke" bei doppelte Zustandsdauer der ersten hat ist kein Zufall, wählt man bei für die X-Achse ein Intervall von 0,412 ms, sieht man schön die vorher mit dem Oszilloskop bestimmten mutmaßlichen Bitlängen. Woher die Häufungen bei "+0,5" (also 1,5-, 3,5-, ...-facher) Bitlängen herkommt, kann man anhand der Datenlage nicht pauschal sagen; hier hilft ein genauerer Blick in die Aufzeichnung: <gallery> ecl_bus_unknown_timings.png </gallery> An der Stelle hatte ich direkt das Glück, zwei solcher "+0,5"-Bitlängen zu erwischen. Wie es scheint ist das einfach ein wenig Padding hinter den eigentlichen Daten. Aber zu den Daten selbst - scrollt man durch die Aufzeichnung sieht man, dass die Frames immer in Rudeln von 5 kommen: <gallery> ecl_bus_packets.png | Zwei Nachrichten ecl_bus_message.png | Eine Nachricht im Detail </gallery> Nimmt man aus dem zweiten Screenshot die einzelnen Frames und legt sie in Bildbearbeitung übereinander, bekommt man sowas ähnliches wie ein Augendiagramm, das ein bisschen bekannt vorkommt: <gallery> ecl_bus_frames_overlay.png | Alle Frames einer Nachricht überlagert </gallery> erstes Bit immer low, letztes Bit immer low, riecht nach UART - allerdings mit etwas ungewöhnlichen 16 Bit Symbollänge. Die vorhin bestimmten etwa 412 µs Bitlänge entspricht etwa 2400 Baud, den Analyzer in Logic damit gefüttert ergibt Daten: <gallery> ecl_bus_message_decoded.png | Eine Nachricht </gallery> Exportiert man die Daten des Analyzers, bekommt man neben sehr vielen <code>0x0000</code> auch zum Beispiel folgendes: <pre>Zeit Daten ... 20,25630025 0x0000 20,27630175 0x60EF 20,29630150 0x1915 20,31630525 0x0CA8 20,33631175 0x0023 20,35631150 0x0D54 20,37631200 0x0000 20,39631075 0x60EF 20,41631625 0x1952 20,43631700 0x6000 20,45631275 0x0045 20,47631425 0x0D5F 20,49632000 0x0000 ... </pre> Zu beachten ist, dass - wie bei UART üblich - das LSB zuerst kommt. Natürlich war ich anfangs nicht so clever und habe ein Python-Script (basierend auf meinem alten C-Code) zum Analysieren der rohen Aufzeichnungen gebastelt. Das Script ist im Abschnitt Downloads zu finden. Dieses kann die Daten wie folgt ausspucken: <pre>12.956395 0x04AF 0x0B1A 0x0000 0x0000 0x0DD8 19.236316 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 20.276302 0x60EF 0x1915 0x0CA8 0x0023 0x0D54 20.396311 0x60EF 0x1952 0x6000 0x0045 0x0D5F 24.036128 0x01F0 0x0A1E 0x22FA 0x0000 0x0D35 25.635993 0x02F0 0x1512 0x030B 0x6779 0x0D07 41.754978 0x04AF 0x0B11 0x0000 0x0000 0x0DCF 42.054995 0x09AF 0x0005 0x0000 0x0000 0x0DBD 42.194992 0x09FA 0xFF0F 0xFFFF 0x00F0 0x0DFF 48.034069 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 49.073926 0x60EF 0x1921 0x0CAB 0x0023 0x0D63 49.193916 0x60EF 0x194B 0x6000 0x0045 0x0D58 52.833398 0x01F0 0x0A1D 0x22FA 0x0000 0x0D34 54.433216 0x02F0 0x152F 0x030B 0x6779 0x0D24 </pre> =Protokoll= Die übliche Vorgehensweise beim Reverse Engineering eines Protokolls ist, bekannte Informationen zu erkennen bzw. zu erzeugen und wiederzufinden. Aufgrund der zurückliegenden Untersuchung des Protokolls kann diese Phase stark abgekürzt werden - das Rad muss schließlich nicht jedes Mal neu erfunden werden. Wer den alten Artikel kennt oder parallel geöffnet hat, wird vermutlich schon erkannt haben, dass die [[wpde:Byte-Reihenfolge|Byte-Reihenfolge]] der Frames unterschiedlich ist. Um ehrlich zu sein: das ist mir damals nicht wirklich aufgefallen, da der Sprung von roher Datenanalyse zum Interpretieren (im AVR) sehr kurz war. Durch die Nichtbeachtung der Endianness bei der Erfassung, Verarbeitung und Ausgabe ging der Punkt einfach verloren. Auch ein Grund, sich nochmal damit auseinanderzusetzen. ==Header== Schaut man sich im letzten Abschnitt den Auszug das Beispiel genauer an, sieht man zumindest im ersten Symbol (bzw. Word) der Daten eine gewisse Wiederholung. Ein einfacher Trick um einen beschränkten Datenraum zu finden ist die Funktion "Duplikate entfernen" in Excel, nachdem die Symbole in Spalten aufgeteilt sind. Während den verschiedenen Aufzeichnungen ließen sich 11 unterschiedliche Nachrichtentypen identifizieren. Hierbei beinhaltet das niederwertige Byte des ersten Word Sender und Empfänger der Nachricht - das höherwertige Nibble ist der Sender, das niederwertige der Empfänger: {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || ECA 60 |- | E || ECA 86 |- | F || ECL 300 |} Höherwertige Byte des ersten Word entspricht dem Nachrichtentyp: {| class="wikitable sortable" |- ! d[0] !! Typ !! Sender !! Empfänger !! Bezeichnung !! Häufigkeit |- | <code>0x04AF</code> || 04 || A || F || Innentemperatur (ECA 60) || 125/h |- | <code>0x05AF</code> || 05 || A || F || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || - |- | <code>0x09AF</code> || 09 || A || F || Abfrage Tagesprogramm || 63/h |- | <code>0x11AF</code> || 11 || A || F || Zeit setzen || - |- | <code>0x60EF</code> || 60 || E || F || Temperaturfühler ECA 86 || 125/h |- | <code>0x01F0</code> || 01 || F || 0 || Außentemperatur || 125/h |- | <code>0x02F0</code> || 02 || F || 0 || Aktuelle Zeit || 125/h |- | <code>0x05FA</code> || 05 || F || A || Solltemperatur am ECL 300 setzen || - |- | <code>0x06FA</code> || 06 || F || A || Bestätigung Setzen Solltemperatur (Antwort auf 05AF) || - |- | <code>0x09FA</code> || 09 || F || A || Tagesprogramm (Antwort auf 06AF) || 63/h |- | <code>0x62FE</code> || 62 || F || E || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine einstündige Datenerfassung, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. ==Prüfsumme== Das höherwertige Byte im letzten Word habe ich immer mit 0x0D beobachtet, das niederwertige Byte ist eine Prüfsumme, die sich als Summe aller Bytes des Headers und der Nutzdaten berechnet: <source lang="javascript"> var data = [ 0x0100, 0x0302, 0x0504, 0x0706, 0x091C ]; var checksum_calc = 0; var checksum_msg = data[4] & 0xFF; for(var i = 0; i < 4; i++) { checksum_calc += (data[i] >> 8) & 0xFF; checksum_calc += (data[i] >> 0) & 0xFF; } checksum_calc &= 0xFF; console.log("calculated checksum: 0x%s, explected 0x%s", checksum_calc.toString(16), checksum_msg.toString(16) ) </source> Wie man darauf kommt fragt ihr? Ausprobieren und ein bisschen Glück. Die "low hanging fruits" sind in Summe, XOR und CRC - bei letzterem kommt allerdings die Schwierigkeit, dass man den passenden Startwert und Polynom finden muss. Bei CRC-8 sind das theoretisch 65536 Kombinationen (wobei für das Polynom auf bestimmte Werte eingeschränkt werden kann). Wird CRC-16 (oder höhere) verwendet, wird die Anzahl der möglichen Kombinationen deutlich größer. ==Payload== Die 3 Words "in der Mitte" sind die eigentlichen Nutzdaten Die Positionsangaben (d[x]) beziehen sich auf dem 0-basierten Index des Words im Paket, die Angabe "Word x" ist ebenfalls 0-basiert. Beispiel: [[Datei:ecl_bus_message_sample.png]] <code> <span style="color: lightgrey"> 04 AF </span> 0B 1A 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 00001011 00011010 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?!!!!!!! !!!!!!!! 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> In der ersten Zeile sind die Werte der Bytes Hexadezimal dargestellt (Little Endian), das zuerst übertragene Word befindet sich links. Die zweite Zeile beinhaltet die binäre Entsprechung des obigen Wertes. Vergleicht man diese Zeile mit dem oben dargestellten Signal auf der Busleitung, ist jedes Word rückwärts abgebildet (LSB first auf dem Bus, MSB first im Text) Die dritte Zeile stellt die "Bekanntheit" des jeweiligen Bits dar: *!: Bedeutung bekannt *?: Bedeutung unbekannt *0: immer low *1: immer high ===04AF: Innentemperatur=== Diese Nachricht überträgt die am ECA 60 gemessene Temperatur an das ECL 300, wo es als Führungsgröße verwendet werden kann <code> <span style="color: lightgrey"> 04 AF </span> <span class="hb1"> 0B 1A </span> 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 0<span class="hb1">0001011 00011010</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?<span class="hb1">!!!!!!! !!!!!!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:0</span></code> || Innentemperatur || x / 128 || 0x0B1A || 22.2<s>03125</s> °C |} Die theoretische Auflösung der Temperatur beträgt 7,8 m°C, wobei der Wert sicher nicht die Genauigkeit hat. Eine Nachkommastelle reicht. Negative Werte werden vermutlich über das aktuell mit ? markierte MSB im Zweierkomplement, was noch bestätigt werden muss. ===05AF/05FA: Solltemperatur, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit)=== *0x05AF: Solltemperatur am ECA 60 setzen, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) *0x05FA: Solltemperatur am ECL 300 setzen <code> <span style="color: lightgrey"> 05 AF </span> <span class="hb1"> 2C </span> FF <span class="hb2"> 0C </span> 24 <span class="hb3"> </span> 82<span class="hb4"> </span> <span class="hb5"> 00 </span> <span style="color: lightgrey"> 0D 91 </span> <span style="color: lightgrey">00000101 10101111</span> 00<span class="hb1">10110</span>0 11111111 0<span class="hb2">000110</span>0 00100100 <span class="hb3">1</span>0000<span class="hb4">010</span> <span class="hb5">0000000</span>0 <span style="color: lightgrey">00001101 10010001</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00<span class="hb1">!!!!!</span>0 ???????? !<span class="hb2">!!!!!!</span>0 ???????? <span class="hb3">!</span>0000<span class="hb4">!!!</span> <span class="hb5">!!!!!!!</span>0 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.13:9</span></code> || Soll-Temperatur || x || 0x16 || 22 °C |- | <code><span class="hb2">2.14:9</span></code> || Abweichende Temperatur (Entspannen) || (s. u.) || 0x06 || +6 °C |- | <code><span class="hb3">3.15</span></code> || Abweichung aktiv || s. u. || 0x01 || aktiv |- | <code><span class="hb4">3.10:8</span></code> || Betriebsmodus || s. u. || || 2 = Konstante Komforttemperatur |- | <code><span class="hb5">3.7:1</span></code> || Abweichende Temperatur (Abwesenheit) || (s. u.) || 0x00 || 0 °C |} Achtung: hier gibt es noch eine kleine Unsicherheit, was <code>1.7:0</code> macht und wie es zu <code><span class="hb1">1.13:9</span></code> steht. ====Abweichende Temperatur==== In den Words <code><span class="hb2">2.14:9</span></code> und <code><span class="hb5">3.7:1</span></code> sind die Abweichungen zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gelten. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - im Byte um ein Bit nach links verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement beachtet werden. Um vorzeichenbehaftete 8 Bit Integer verwenden zu können, werden im Code die folgenden Bits ersetzt: <source lang="C"> if(type == ECL_DIFF_RELAX) { ecl_data.tmp_diff = (buff[2] >> 9) & 0x7F; if(ecl_data.tmp_diff & 0x20) { ecl_data.tmp_diff |= 0xC0; } } else if(type == ECL_DIFF_AWAY) { ecl_data.tmp_diff = (buff[3] >> 1) & 0x7F; if(ecl_data.tmp_diff & 0x40) { ecl_data.tmp_diff |= 0x80; } } </source> Das Setzen von Abweichungen ist etwas merkwürdig: Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und Wiederverbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEPROM des ECA 60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5 °C bei Abwesenheit oder -10 °C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21 °C mit -10 °C (also Solltemperatur 11 °C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern. ====Betriebsmodus==== {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Manuell |- | 001 || 1 || Zeitgesteuerter Betrieb |- | 010 || 2 || Konstante Komforttemperatur |- | 011 || 3 || Konstante reduzierte Temperatur |- | 100 || 4 || Standby |} Die restlichen zustände sind mir nicht bekannt. ===06AF/06FA: Bestätigung Setzen Solltemperatur (Antwort auf 05AF)=== Diese Nachricht dient offenbar der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (06FA folgt auf 05AF bw. 06AF folgt auf 05FA) direkt nach einem 05**-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden. ===09AF: Abfrage Tagesprogramm=== Abfrage des Tagesprogrammes für den Heizkreis durch ECA 60. <code> <span style="color: lightgrey"> 09 AF </span> 00 04<span class="hb1"> </span> 00 00 00 00 <span style="color: lightgrey"> 0D BC </span> <span style="color: lightgrey">00001001 10101111</span> 00000000 00000<span class="hb1">100</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 10111100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00000000 00000<span class="hb1">!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.2:0</span></code> || Wochentag || 0=Montag ... 7=Sonntag || 0x04 || Freitag |} Die Ermittlung des Wochentags ist eigentlich klare Sache, aber der Vollständigkeit halber: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Montag |- | 001 || 1 || Dienstag |- | 010 || 2 || Mittwoch |- | 011 || 3 || Donnerstag |- | 100 || 4 || Freitag |- | 101 || 5 || Samstag |- | 110 || 6 || Sonntag |} ===09FA: Rückmeldung Tagesprogramm=== Rückmeldung des Heizkreis-Tagesprogrammes auf Abfrage in 09AF. <code> <span style="color: lightgrey"> 09 FA </span> <span class="hb1"> FF 3F 81 FF 00 FE </span> <span style="color: lightgrey"> 0D BF </span> <span style="color: lightgrey">00001001 11111010</span> <span class="hb1">11111111 00111111 10000001 11111111 00000000 11111110</span> <span style="color: lightgrey">00001101 10111111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:3.0</span></code> || Tagesprogramm als Bitmap || s. u. || s. u. |} Hier habe ich echte Zweifel bekommen, ob die Endianness richtig ist. Um kurz die Fakten zu nennen: Jedes Bit entspricht eine halbe Stunde, in dem Beispiel gibt es zwei Heizphasen: [[Datei:ecl_tagesprogramm.jpg|300px]] also: *04:30 - 08:30 *11:30 - 23:00 Um die Bitmap intuitiver zu bekommen, ist es am einfachsten, die Endianness zu ändern - so wird aus dem Beispiel von oben: <code> <span class="hb1"> 0xFF3F </span><span class="hb2"> 0x81FF </span><span class="hb3"> 0x00FE </span> LE: <span class="hb1">1111111100111111</span><span class="hb2">1000000111111111</span><span class="hb3">0000000011111110</span> BE: <span class="hb1">0011111111111111</span><span class="hb2">1111111110000001</span><span class="hb3">1111111000000000</span> </code> So wird schon eher ein Schuh draus: rechts ist 00:00, links 24:00 - das deckt sich mit der Darstellung oben. ===11AF/02F0: Zeit setzen/aktuelle Zeit=== <code> <span style="color: lightgrey"> 11 AF </span> <span class="hb1"> 03 </span> <span class="hb2"> 20 </span> <span class="hb3"> 05 </span> <span class="hb4"> 0D </span> <span class="hb5"> 7</span><span class="hb6">9 </span> <span class="hb7"> 79 </span> <span style="color: lightgrey"> 0D E7 </span> <span style="color: lightgrey">00010001 10101111</span> 0<span class="hb1">0000011</span> 0<span class="hb2">0100000</span> 00<span class="hb3">000101</span> 00<span class="hb4">001101</span> 0<span class="hb5">111</span><span class="hb6">1001</span> <span class="hb7">01111001</span> <span style="color: lightgrey">00001101 11100111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 0<span class="hb1">!!!!!!!</span> 0<span class="hb2">!!!!!!!</span> 00<span class="hb3">!!!!!!</span> 00<span class="hb4">!!!!!!</span> ?<span class="hb5">!!!</span><span class="hb6">!!!!</span> <span class="hb7">!!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:8</span></code> || Minuten || x || 0x03 || 3 |- | <code><span class="hb2">1.6:0</span></code> || Sekunden || x || 0x20 || 32 |- | <code><span class="hb3">2.13:8</span></code> || Tag || x || 0x05 || 5 |- | <code><span class="hb4">2.5:0</span></code> || Stunden || x || 0x0D || 13 |- | <code><span class="hb5">3.15:12</span></code> || Wochentag || 1=Montag ... 7=Sonntag || 0x07 || Sonntag |- | <code><span class="hb6">3.11:8</span></code> || Monat || x || 0x09 || 9 |- | <code><span class="hb7">3.7:0</span></code> || Jahr || 1900 + x || 0x79 || 2021 |} In dieser Nachricht wird also Sonntag, 2021-09-05 13:03:32 als aktuelles Datum & Zeit gesetzt. Die Sekunden können zumindest am ECA 60 nicht eingestellt werden. Bemerkenswert ist hier, dass bei dieser Nachricht der Wochentag nicht wie in Nachricht 0x09AF nicht bei 0, sondern bei 1 beginnt. Eine Vermutung könnte sein, dass ein Wert von "0" die ECL 300 veranlasst, den Wochentag selbst zu berechnen, was ich jedoch nicht beobachten konnte. Wieder der Vollständigkeit halber hier die Lookup-Tabelle der Wochentage: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 001 || 1 || Montag |- | 010 || 2 || Dienstag |- | 011 || 3 || Mittwoch |- | 100 || 4 || Donnerstag |- | 101 || 5 || Freitag |- | 110 || 6 || Samstag |- | 111 || 7 || Sonntag |} ===60EF: Temperaturfühler ECA 86=== Mit dieser Nachricht werden die vom ECA 86 gemessenen Temperaturen übertragen. Das Modul verfügt über 4 Sensoreingänge, die Übertragung der Messwerte erfolgt in zwei Nachrichten. <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1E DB </span> <span class="hb2"> 0B 96 </span> 00 <span class="hb3"> 2</span><span class="hb4">3 </span> <span style="color: lightgrey"> 0D 0C </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011110 11011011</span> <span class="hb2">00001011 10010110</span> 00000000 <span class="hb3">0010</span><span class="hb4">0011</span> <span style="color: lightgrey">00001101 00001100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> <span class="hb2">!!!!!!!! !!!!!!!!</span> 00000000 <span class="hb3">!!!!</span><span class="hb4">!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1EDB || 61,7<s>109375</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x0B96 || 23,1<s>71875</s> °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x02 || 2 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x03 || 3 |} Für die zweite Gruppe sieht die Nachricht wie folgt aus: <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1F 2F </span> <span class="hb2"> 60 00 </span> 00 <span class="hb3"> 4</span><span class="hb4">5 </span> <span style="color: lightgrey"> 0D 42 </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011111 00101111</span> <span class="hb2">01100000 00000000</span> 00000000 <span class="hb3">0100</span><span class="hb4">0101</span> <span style="color: lightgrey">00001101 01000010</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1F2F || 62,3<s>671875</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x6000 || 192 °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x04 || 4 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x05 || 5 |} Index 1 und 2 konnten noch nicht beobachtet werden, Index 5 entspricht dem ungenutzten Eingang 4, der mit einem Widerstand terminiert ist. Dementsprechend ist davon auszugehen, dass die Indizes einfach um 2 verschoben sind. ===01F0: Außentemperatur=== <code> <span style="color: lightgrey"> 01 F0 </span> <span class="hb1"> 0A 06 </span> <span class="hb2"> 2</span>2 <span class="hb3"> </span> FA 00 00 <span style="color: lightgrey"> 0D 1D </span> <span style="color: lightgrey">00000001 11110000</span> <span class="hb1">00001010 00000110</span> 00<span class="hb2">10</span>00<span class="hb3">10</span> 11111010 00000000 00000000 <span style="color: lightgrey">00001101 00011101</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> ??<span class="hb2">!!</span>??<span class="hb3">!!</span> ???????? 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Außentemperatur || x / 128 || 0x0A06 || 20,0<s>46875</s> °C |- | <code><span class="hb2">2.13:12</span></code> || Betriebsmodus Brauchwasserkreis || s. u. || 0x02 || Komforttemperatur |- | <code><span class="hb3">2.9:8</span></code> || Betriebsmodus Heizkreis || s. u. || 0x02 || Komforttemperatur |} Der Betriebsmodus wird vermutlich nach folgender Tabelle bestimmt: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Reduzierte Temperatur |- | 01 || 1 || Optimierte Aufheizphase |- | 10 || 2 || Komforttemperatur |- | 11 || 3 || Optimierte Absenkphase |} Bisher habe ich nur Modus 0 und 2 gesehen, die anderen beiden stammen aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet. ===62FE: Setzen Relais an ECA 86=== <code> <span style="color: lightgrey"> 62 FE </span> FF FF FF FF 00 00 <span style="color: lightgrey"> 0D 5C </span> <span style="color: lightgrey">01100010 11111110</span> 11111111 11111111 11111111 11111111 00000000 00000000 <span style="color: lightgrey">00001101 01011100</span> </code> Da die Heizung während der Aufzeichnungen nie aktiv war, gibt es hierzu noch keine Informationen. ===Alarmmodul=== Das Alarmmodul ist leider nicht am ECL Bus (sondern am ECL 300) angeschlossen, auch konnte ich keine Nachrichten ausmachen, in dem ein etwaiger Alarmzustand übertragen wird. Dadurch ist die Ferndiagnose über den ECL-Bus leider in weite Ferne gerückt. =Downloads= *[[Datei:Ecl_bus_data.zip]] Aufzeichnungen (Saleae Logic 2.3.35), gefilterte, und gesparste Daten und Python-Scripts zum Filtern/Parsen. Bitte beachten: Die Aufzeichnungen in Logic sind invertiert [[Kategorie:Haustechnik]] [[Kategorie:Energieerfassung]] [[Kategorie:Reverse Engineering]] d0dedf1adebcda78a35b8f8b7a0bf487dc258223 1697 1696 2021-09-07T18:38:44Z Chris 2 /* Einbaumodule */ Typo wikitext text/x-wiki Neue Erfahrungen bringen neue Sichtweisen. Unter dieser Prämisse - und nachdem ich den Artikel des [[ECL-Bus-Decoder]]s selbst nicht mehr ganz verstanden habe - entschied ich mich, das Ganze nochmal anzuschauen. Worum geht es? Bei der Heizungsanlage meiner Eltern - genauer einer Grundwasser-Wärmepumpe - ist ein Regler von Danfoss verbaut. Genauer ein ECL 300. Dieser verwendet zur Kommunikation mit seinen externen Modulen den so genannten ECL-Bus, der zwar in der Anleitung erwähnt, aber keine weiteren Details genannt werden. Auch der Support von Danfoss schwieg sich bei einer Anfrage vor einigen Jahren darüber (und die RS-232-Schnittstelle an der Front des ECL 300) aus: "Es gibt keine Dokumentation". Oder vielmehr: Es gibt keine Dokumentation, die für die Öffentlichkeit bestimmt ist. "Kein Problem, dann mach ich halt eine" war mein Gedanke damals, woraufhin der oben genannte Artikel entstand. =Busteilnehmer= Lt. meiner Recherchen gibt/gab es folgende Geräte für das System (untersuchte sind fett markiert): * '''ECL 300''': elektronischer Temperaturregler (ECL 301 ist die 24 V-Version) * '''ECA 60''': Raumleitgerät mit Temperaturmessung * ECA 62: Raumleitgerät mit Temperatur- und Luftfeuchtemessung * ECA 61/63: Im Prinzip wie ECA 60/62, nur werden diese als "Remote control" statt "Room panels" bezeichnet * '''ECA 86''': Temperatur-Alarm- & Relaismodul für ECL 30x (4x Temperatur, 2x Relais) ==ECL 300== [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Der/Die/Das ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. ==ECA 86== [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt. ==ECA 60== [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEPROM 93C66A (512x8 bit) gespeichert. Auf der Rückseite des Gerätes befindet sich ein Schalter zum Wählen der Adresse (A und B), ein Umschalten auf B bezweckt lediglich, dass das Raumleitgerät ewig im Init-Zustand (keine Anzeige von Messwerten) bleibt. =Einbaumodule= Ferner bin ich über folgende Einsteckmodule für die ECL 30x gestoßen: * ECA 71: Modbus-Adapter für die ECL 30x * ECA 81: RS-232-Adapter für die ECL 30x * ECA 87: RS-232-Datenlogger In der Anleitung des ECA 81 wird gleich auf der ersten Seite darauf hingewiesen ''"Es ist kein Protokoll für die ECA 81 RS 232 Kommunikation vorhanden. ECA 81 dient nur der Kommunikation mit der Danfoss ECL Comfort Service Software."'' Die Anleitung des ECA 87 beinhaltet die Information, dass die Einsteckmodule (u. a.?) über SPI kommunizieren - und immerhin ist das Protokoll dafür beschrieben. Am Frontpanel der ECL 30x befindet sich allerdings schon eine RS-232-Schnittstelle, die allerdings ein anderes Protokoll spricht. In dem Sinne: Danke für nichts. =Schnittstelle= Wie eingangs angedeutet, gibt es nicht sonderlich viele öffentlich verfügbare Informationen über die Schnittstelle. Aus der Installationsanleitung lässt sich allerdings drauf schließen, dass es ein eindrahtiges Bus-System ist: Am Regler ist Klemme 15 mit "BUS" gekennzeichnet, Klemme 16 mit GND (an der auch die Temperaturfühler terminiert sind). ==Physischer Layer== Da die Raumleitgeräte keine eigene Versorgung haben ist ferner anzunehmen, dass es eine Phantomspeisung gibt. Mit dem Multimeter ließen sich um die 24 V Wechselspannung mit 50 Hz messen, also spricht nichts dagegen, auch mal das Oszi anzuklemmen. Im Ruhezustand bestätigt das Oszi in etwa das, was das Multimeter gemessen hat: Ein 50 Hz-Rechteck-Signal mit etwa 26 V Amplitude und 64 % Duty-Cycle: <gallery> ecl_bus_idle.png | Signalverlauf des ECL-Bus im Ruhezustand </gallery> Drückt man oft genug auf Run/Stop erwischt man auch mal ein bisschen mehr Gezappel als die 50 Hz: <gallery> ecl_bus_transmit.png | ecl_bus_timing.png | </gallery> Mit ein bisschen mehr Zoom lassen sich auch die mutmaßlichen Bitdauern messen - 2,06 ms für 5 Zustandswechsel ergibt 412 µs / "Bit". Mutmaßlich und in Anführungszeichen, da noch nicht bekannt sind, wie genau die Daten übertragen werden. Ist man mit der Run/Stop-Taste geduldiger als mit dem Einstellen eines cleveren Triggers, bekommt man irgendwann folgendes auf den Schirm: <gallery> ecl_bus_receive.png | ecl_bus_receive_frame.png | ecl_bus_receive_timing.png | </gallery> Das sieht doch schon eher nach vollständiger Nachricht aus. Auffällig ist zudem, dass die Pegel der Kommunikation ein Stück niedriger sind als in den Screenshots weiter oben (und zum 50 Hz-Rechteck). Das könnte ein Unterschied zwischen den Teilnehmern sein: Angenommen das zuvor gezeigte Signal ist vom ECL 300, dann ist es naheliegend, dass die selbe Schaltung Versorgung (Erzeugung der 50 Hz) wie zur Kommunikation verwendet wird. Ein Busteilnehmer, insbesondere wenn dieser über den Bus gespeist wird, hat eine andere (tendenziell niedrigere) Spannung, mit der der Bus getrieben werden kann. Beim Blick auf ein Frame auch wieder eine Messung der mutmaßlichen Bitlänge: 3,3 ms für 8 Übergänge = 412,5 µs / "Bit", also sehr nah am Wert von oben. ==Bitübertragung== Aufzeichnungen vom Oszilloskop sind etwas dröge in Sachen Protokoll-Reverse-Engineering - zumindest, wenn man es auch mit einem Logic-Analyzer machen kann. Als Schnittstelle zum LA dient (wie bereits vorher erfolgreich getestet) ein einfacher Optokoppler mit passenden Vorwiderständen. Neben den üblichen Aufzeichnungen mit verschiedenen Aktionen am Gerät lief die Aufzeichnungen auch einfach mal für 10 Minuten ohne besondere Aktivität. Mit ein bisschen Excel-Datenschubserei purzelten zwei Histogramme über die Häufigkeit der verschiedenen Zustandsdauern heraus: <gallery> ecl_bus_bitlenhisto1.png | Histogramm über alle Bitlängen ecl_bus_bitlenhisto2.png | Histogramm über Bitlängen bis 1 ms ecl_bus_bitlenhisto3.png | Histogramm mit besonderer X-Achse </gallery> Zu berücksichtigen ist, dass Low- und High-Zustände gleich dargestellt sind. Im ersten Diagramm sieht man halbwegs gut, dass die Zustände um 7,2 ms und 12,8 ms weitaus am häufigsten eingenommen werden (hier sollte die Kombination aus logarithmischer Skala und Clustergröße 0,001 ms im Hinterkopf behalten werden). In der Summe der beiden Zahlen findet man die Periodendauer der 50 Hz der Versorgung wieder. Schaut man sich einen deutlich kleineren Wertebereich (zweites Diagramm) an sieht man, dass sich bei 0,4-nochwas und 0,8-nochwas Millisekunden mit etwas Phantasie [[wpde:Normalverteilung|normalverteilte Kurven]] ergeben. Dass die zweite "Glocke" bei doppelte Zustandsdauer der ersten hat ist kein Zufall, wählt man bei für die X-Achse ein Intervall von 0,412 ms, sieht man schön die vorher mit dem Oszilloskop bestimmten mutmaßlichen Bitlängen. Woher die Häufungen bei "+0,5" (also 1,5-, 3,5-, ...-facher) Bitlängen herkommt, kann man anhand der Datenlage nicht pauschal sagen; hier hilft ein genauerer Blick in die Aufzeichnung: <gallery> ecl_bus_unknown_timings.png </gallery> An der Stelle hatte ich direkt das Glück, zwei solcher "+0,5"-Bitlängen zu erwischen. Wie es scheint ist das einfach ein wenig Padding hinter den eigentlichen Daten. Aber zu den Daten selbst - scrollt man durch die Aufzeichnung sieht man, dass die Frames immer in Rudeln von 5 kommen: <gallery> ecl_bus_packets.png | Zwei Nachrichten ecl_bus_message.png | Eine Nachricht im Detail </gallery> Nimmt man aus dem zweiten Screenshot die einzelnen Frames und legt sie in Bildbearbeitung übereinander, bekommt man sowas ähnliches wie ein Augendiagramm, das ein bisschen bekannt vorkommt: <gallery> ecl_bus_frames_overlay.png | Alle Frames einer Nachricht überlagert </gallery> erstes Bit immer low, letztes Bit immer low, riecht nach UART - allerdings mit etwas ungewöhnlichen 16 Bit Symbollänge. Die vorhin bestimmten etwa 412 µs Bitlänge entspricht etwa 2400 Baud, den Analyzer in Logic damit gefüttert ergibt Daten: <gallery> ecl_bus_message_decoded.png | Eine Nachricht </gallery> Exportiert man die Daten des Analyzers, bekommt man neben sehr vielen <code>0x0000</code> auch zum Beispiel folgendes: <pre>Zeit Daten ... 20,25630025 0x0000 20,27630175 0x60EF 20,29630150 0x1915 20,31630525 0x0CA8 20,33631175 0x0023 20,35631150 0x0D54 20,37631200 0x0000 20,39631075 0x60EF 20,41631625 0x1952 20,43631700 0x6000 20,45631275 0x0045 20,47631425 0x0D5F 20,49632000 0x0000 ... </pre> Zu beachten ist, dass - wie bei UART üblich - das LSB zuerst kommt. Natürlich war ich anfangs nicht so clever und habe ein Python-Script (basierend auf meinem alten C-Code) zum Analysieren der rohen Aufzeichnungen gebastelt. Das Script ist im Abschnitt Downloads zu finden. Dieses kann die Daten wie folgt ausspucken: <pre>12.956395 0x04AF 0x0B1A 0x0000 0x0000 0x0DD8 19.236316 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 20.276302 0x60EF 0x1915 0x0CA8 0x0023 0x0D54 20.396311 0x60EF 0x1952 0x6000 0x0045 0x0D5F 24.036128 0x01F0 0x0A1E 0x22FA 0x0000 0x0D35 25.635993 0x02F0 0x1512 0x030B 0x6779 0x0D07 41.754978 0x04AF 0x0B11 0x0000 0x0000 0x0DCF 42.054995 0x09AF 0x0005 0x0000 0x0000 0x0DBD 42.194992 0x09FA 0xFF0F 0xFFFF 0x00F0 0x0DFF 48.034069 0x62FE 0xFFFF 0xFFFF 0x0000 0x0D5C 49.073926 0x60EF 0x1921 0x0CAB 0x0023 0x0D63 49.193916 0x60EF 0x194B 0x6000 0x0045 0x0D58 52.833398 0x01F0 0x0A1D 0x22FA 0x0000 0x0D34 54.433216 0x02F0 0x152F 0x030B 0x6779 0x0D24 </pre> =Protokoll= Die übliche Vorgehensweise beim Reverse Engineering eines Protokolls ist, bekannte Informationen zu erkennen bzw. zu erzeugen und wiederzufinden. Aufgrund der zurückliegenden Untersuchung des Protokolls kann diese Phase stark abgekürzt werden - das Rad muss schließlich nicht jedes Mal neu erfunden werden. Wer den alten Artikel kennt oder parallel geöffnet hat, wird vermutlich schon erkannt haben, dass die [[wpde:Byte-Reihenfolge|Byte-Reihenfolge]] der Frames unterschiedlich ist. Um ehrlich zu sein: das ist mir damals nicht wirklich aufgefallen, da der Sprung von roher Datenanalyse zum Interpretieren (im AVR) sehr kurz war. Durch die Nichtbeachtung der Endianness bei der Erfassung, Verarbeitung und Ausgabe ging der Punkt einfach verloren. Auch ein Grund, sich nochmal damit auseinanderzusetzen. ==Header== Schaut man sich im letzten Abschnitt den Auszug das Beispiel genauer an, sieht man zumindest im ersten Symbol (bzw. Word) der Daten eine gewisse Wiederholung. Ein einfacher Trick um einen beschränkten Datenraum zu finden ist die Funktion "Duplikate entfernen" in Excel, nachdem die Symbole in Spalten aufgeteilt sind. Während den verschiedenen Aufzeichnungen ließen sich 11 unterschiedliche Nachrichtentypen identifizieren. Hierbei beinhaltet das niederwertige Byte des ersten Word Sender und Empfänger der Nachricht - das höherwertige Nibble ist der Sender, das niederwertige der Empfänger: {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || ECA 60 |- | E || ECA 86 |- | F || ECL 300 |} Höherwertige Byte des ersten Word entspricht dem Nachrichtentyp: {| class="wikitable sortable" |- ! d[0] !! Typ !! Sender !! Empfänger !! Bezeichnung !! Häufigkeit |- | <code>0x04AF</code> || 04 || A || F || Innentemperatur (ECA 60) || 125/h |- | <code>0x05AF</code> || 05 || A || F || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || - |- | <code>0x09AF</code> || 09 || A || F || Abfrage Tagesprogramm || 63/h |- | <code>0x11AF</code> || 11 || A || F || Zeit setzen || - |- | <code>0x60EF</code> || 60 || E || F || Temperaturfühler ECA 86 || 125/h |- | <code>0x01F0</code> || 01 || F || 0 || Außentemperatur || 125/h |- | <code>0x02F0</code> || 02 || F || 0 || Aktuelle Zeit || 125/h |- | <code>0x05FA</code> || 05 || F || A || Solltemperatur am ECL 300 setzen || - |- | <code>0x06FA</code> || 06 || F || A || Bestätigung Setzen Solltemperatur (Antwort auf 05AF) || - |- | <code>0x09FA</code> || 09 || F || A || Tagesprogramm (Antwort auf 06AF) || 63/h |- | <code>0x62FE</code> || 62 || F || E || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine einstündige Datenerfassung, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. ==Prüfsumme== Das höherwertige Byte im letzten Word habe ich immer mit 0x0D beobachtet, das niederwertige Byte ist eine Prüfsumme, die sich als Summe aller Bytes des Headers und der Nutzdaten berechnet: <source lang="javascript"> var data = [ 0x0100, 0x0302, 0x0504, 0x0706, 0x091C ]; var checksum_calc = 0; var checksum_msg = data[4] & 0xFF; for(var i = 0; i < 4; i++) { checksum_calc += (data[i] >> 8) & 0xFF; checksum_calc += (data[i] >> 0) & 0xFF; } checksum_calc &= 0xFF; console.log("calculated checksum: 0x%s, explected 0x%s", checksum_calc.toString(16), checksum_msg.toString(16) ) </source> Wie man darauf kommt fragt ihr? Ausprobieren und ein bisschen Glück. Die "low hanging fruits" sind in Summe, XOR und CRC - bei letzterem kommt allerdings die Schwierigkeit, dass man den passenden Startwert und Polynom finden muss. Bei CRC-8 sind das theoretisch 65536 Kombinationen (wobei für das Polynom auf bestimmte Werte eingeschränkt werden kann). Wird CRC-16 (oder höhere) verwendet, wird die Anzahl der möglichen Kombinationen deutlich größer. ==Payload== Die 3 Words "in der Mitte" sind die eigentlichen Nutzdaten Die Positionsangaben (d[x]) beziehen sich auf dem 0-basierten Index des Words im Paket, die Angabe "Word x" ist ebenfalls 0-basiert. Beispiel: [[Datei:ecl_bus_message_sample.png]] <code> <span style="color: lightgrey"> 04 AF </span> 0B 1A 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 00001011 00011010 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?!!!!!!! !!!!!!!! 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> In der ersten Zeile sind die Werte der Bytes Hexadezimal dargestellt (Little Endian), das zuerst übertragene Word befindet sich links. Die zweite Zeile beinhaltet die binäre Entsprechung des obigen Wertes. Vergleicht man diese Zeile mit dem oben dargestellten Signal auf der Busleitung, ist jedes Word rückwärts abgebildet (LSB first auf dem Bus, MSB first im Text) Die dritte Zeile stellt die "Bekanntheit" des jeweiligen Bits dar: *!: Bedeutung bekannt *?: Bedeutung unbekannt *0: immer low *1: immer high ===04AF: Innentemperatur=== Diese Nachricht überträgt die am ECA 60 gemessene Temperatur an das ECL 300, wo es als Führungsgröße verwendet werden kann <code> <span style="color: lightgrey"> 04 AF </span> <span class="hb1"> 0B 1A </span> 00 00 00 00 <span style="color: lightgrey"> 0D D8 </span> <span style="color: lightgrey">00000100 10101111</span> 0<span class="hb1">0001011 00011010</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 11011000</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> ?<span class="hb1">!!!!!!! !!!!!!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:0</span></code> || Innentemperatur || x / 128 || 0x0B1A || 22.2<s>03125</s> °C |} Die theoretische Auflösung der Temperatur beträgt 7,8 m°C, wobei der Wert sicher nicht die Genauigkeit hat. Eine Nachkommastelle reicht. Negative Werte werden vermutlich über das aktuell mit ? markierte MSB im Zweierkomplement, was noch bestätigt werden muss. ===05AF/05FA: Solltemperatur, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit)=== *0x05AF: Solltemperatur am ECA 60 setzen, vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) *0x05FA: Solltemperatur am ECL 300 setzen <code> <span style="color: lightgrey"> 05 AF </span> <span class="hb1"> 2C </span> FF <span class="hb2"> 0C </span> 24 <span class="hb3"> </span> 82<span class="hb4"> </span> <span class="hb5"> 00 </span> <span style="color: lightgrey"> 0D 91 </span> <span style="color: lightgrey">00000101 10101111</span> 00<span class="hb1">10110</span>0 11111111 0<span class="hb2">000110</span>0 00100100 <span class="hb3">1</span>0000<span class="hb4">010</span> <span class="hb5">0000000</span>0 <span style="color: lightgrey">00001101 10010001</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00<span class="hb1">!!!!!</span>0 ???????? !<span class="hb2">!!!!!!</span>0 ???????? <span class="hb3">!</span>0000<span class="hb4">!!!</span> <span class="hb5">!!!!!!!</span>0 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.13:9</span></code> || Soll-Temperatur || x || 0x16 || 22 °C |- | <code><span class="hb2">2.14:9</span></code> || Abweichende Temperatur (Entspannen) || (s. u.) || 0x06 || +6 °C |- | <code><span class="hb3">3.15</span></code> || Abweichung aktiv || s. u. || 0x01 || aktiv |- | <code><span class="hb4">3.10:8</span></code> || Betriebsmodus || s. u. || || 2 = Konstante Komforttemperatur |- | <code><span class="hb5">3.7:1</span></code> || Abweichende Temperatur (Abwesenheit) || (s. u.) || 0x00 || 0 °C |} Achtung: hier gibt es noch eine kleine Unsicherheit, was <code>1.7:0</code> macht und wie es zu <code><span class="hb1">1.13:9</span></code> steht. ====Abweichende Temperatur==== In den Words <code><span class="hb2">2.14:9</span></code> und <code><span class="hb5">3.7:1</span></code> sind die Abweichungen zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gelten. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - im Byte um ein Bit nach links verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement beachtet werden. Um vorzeichenbehaftete 8 Bit Integer verwenden zu können, werden im Code die folgenden Bits ersetzt: <source lang="C"> if(type == ECL_DIFF_RELAX) { ecl_data.tmp_diff = (buff[2] >> 9) & 0x7F; if(ecl_data.tmp_diff & 0x20) { ecl_data.tmp_diff |= 0xC0; } } else if(type == ECL_DIFF_AWAY) { ecl_data.tmp_diff = (buff[3] >> 1) & 0x7F; if(ecl_data.tmp_diff & 0x40) { ecl_data.tmp_diff |= 0x80; } } </source> Das Setzen von Abweichungen ist etwas merkwürdig: Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und Wiederverbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEPROM des ECA 60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5 °C bei Abwesenheit oder -10 °C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21 °C mit -10 °C (also Solltemperatur 11 °C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern. ====Betriebsmodus==== {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Manuell |- | 001 || 1 || Zeitgesteuerter Betrieb |- | 010 || 2 || Konstante Komforttemperatur |- | 011 || 3 || Konstante reduzierte Temperatur |- | 100 || 4 || Standby |} Die restlichen zustände sind mir nicht bekannt. ===06AF/06FA: Bestätigung Setzen Solltemperatur (Antwort auf 05AF)=== Diese Nachricht dient offenbar der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (06FA folgt auf 05AF bw. 06AF folgt auf 05FA) direkt nach einem 05**-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden. ===09AF: Abfrage Tagesprogramm=== Abfrage des Tagesprogrammes für den Heizkreis durch ECA 60. <code> <span style="color: lightgrey"> 09 AF </span> 00 04<span class="hb1"> </span> 00 00 00 00 <span style="color: lightgrey"> 0D BC </span> <span style="color: lightgrey">00001001 10101111</span> 00000000 00000<span class="hb1">100</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 10111100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 00000000 00000<span class="hb1">!!!</span> 00000000 00000000 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.2:0</span></code> || Wochentag || 0=Montag ... 7=Sonntag || 0x04 || Freitag |} Die Ermittlung des Wochentags ist eigentlich klare Sache, aber der Vollständigkeit halber: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Montag |- | 001 || 1 || Dienstag |- | 010 || 2 || Mittwoch |- | 011 || 3 || Donnerstag |- | 100 || 4 || Freitag |- | 101 || 5 || Samstag |- | 110 || 6 || Sonntag |} ===09FA: Rückmeldung Tagesprogramm=== Rückmeldung des Heizkreis-Tagesprogrammes auf Abfrage in 09AF. <code> <span style="color: lightgrey"> 09 FA </span> <span class="hb1"> FF 3F 81 FF 00 FE </span> <span style="color: lightgrey"> 0D BF </span> <span style="color: lightgrey">00001001 11111010</span> <span class="hb1">11111111 00111111 10000001 11111111 00000000 11111110</span> <span style="color: lightgrey">00001101 10111111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:3.0</span></code> || Tagesprogramm als Bitmap || s. u. || s. u. |} Hier habe ich echte Zweifel bekommen, ob die Endianness richtig ist. Um kurz die Fakten zu nennen: Jedes Bit entspricht eine halbe Stunde, in dem Beispiel gibt es zwei Heizphasen: [[Datei:ecl_tagesprogramm.jpg|300px]] also: *04:30 - 08:30 *11:30 - 23:00 Um die Bitmap intuitiver zu bekommen, ist es am einfachsten, die Endianness zu ändern - so wird aus dem Beispiel von oben: <code> <span class="hb1"> 0xFF3F </span><span class="hb2"> 0x81FF </span><span class="hb3"> 0x00FE </span> LE: <span class="hb1">1111111100111111</span><span class="hb2">1000000111111111</span><span class="hb3">0000000011111110</span> BE: <span class="hb1">0011111111111111</span><span class="hb2">1111111110000001</span><span class="hb3">1111111000000000</span> </code> So wird schon eher ein Schuh draus: rechts ist 00:00, links 24:00 - das deckt sich mit der Darstellung oben. ===11AF/02F0: Zeit setzen/aktuelle Zeit=== <code> <span style="color: lightgrey"> 11 AF </span> <span class="hb1"> 03 </span> <span class="hb2"> 20 </span> <span class="hb3"> 05 </span> <span class="hb4"> 0D </span> <span class="hb5"> 7</span><span class="hb6">9 </span> <span class="hb7"> 79 </span> <span style="color: lightgrey"> 0D E7 </span> <span style="color: lightgrey">00010001 10101111</span> 0<span class="hb1">0000011</span> 0<span class="hb2">0100000</span> 00<span class="hb3">000101</span> 00<span class="hb4">001101</span> 0<span class="hb5">111</span><span class="hb6">1001</span> <span class="hb7">01111001</span> <span style="color: lightgrey">00001101 11100111</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> 0<span class="hb1">!!!!!!!</span> 0<span class="hb2">!!!!!!!</span> 00<span class="hb3">!!!!!!</span> 00<span class="hb4">!!!!!!</span> ?<span class="hb5">!!!</span><span class="hb6">!!!!</span> <span class="hb7">!!!!!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.14:8</span></code> || Minuten || x || 0x03 || 3 |- | <code><span class="hb2">1.6:0</span></code> || Sekunden || x || 0x20 || 32 |- | <code><span class="hb3">2.13:8</span></code> || Tag || x || 0x05 || 5 |- | <code><span class="hb4">2.5:0</span></code> || Stunden || x || 0x0D || 13 |- | <code><span class="hb5">3.15:12</span></code> || Wochentag || 1=Montag ... 7=Sonntag || 0x07 || Sonntag |- | <code><span class="hb6">3.11:8</span></code> || Monat || x || 0x09 || 9 |- | <code><span class="hb7">3.7:0</span></code> || Jahr || 1900 + x || 0x79 || 2021 |} In dieser Nachricht wird also Sonntag, 2021-09-05 13:03:32 als aktuelles Datum & Zeit gesetzt. Die Sekunden können zumindest am ECA 60 nicht eingestellt werden. Bemerkenswert ist hier, dass bei dieser Nachricht der Wochentag nicht wie in Nachricht 0x09AF nicht bei 0, sondern bei 1 beginnt. Eine Vermutung könnte sein, dass ein Wert von "0" die ECL 300 veranlasst, den Wochentag selbst zu berechnen, was ich jedoch nicht beobachten konnte. Wieder der Vollständigkeit halber hier die Lookup-Tabelle der Wochentage: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 001 || 1 || Montag |- | 010 || 2 || Dienstag |- | 011 || 3 || Mittwoch |- | 100 || 4 || Donnerstag |- | 101 || 5 || Freitag |- | 110 || 6 || Samstag |- | 111 || 7 || Sonntag |} ===60EF: Temperaturfühler ECA 86=== Mit dieser Nachricht werden die vom ECA 86 gemessenen Temperaturen übertragen. Das Modul verfügt über 4 Sensoreingänge, die Übertragung der Messwerte erfolgt in zwei Nachrichten. <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1E DB </span> <span class="hb2"> 0B 96 </span> 00 <span class="hb3"> 2</span><span class="hb4">3 </span> <span style="color: lightgrey"> 0D 0C </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011110 11011011</span> <span class="hb2">00001011 10010110</span> 00000000 <span class="hb3">0010</span><span class="hb4">0011</span> <span style="color: lightgrey">00001101 00001100</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> <span class="hb2">!!!!!!!! !!!!!!!!</span> 00000000 <span class="hb3">!!!!</span><span class="hb4">!!!!</span> <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1EDB || 61,7<s>109375</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x0B96 || 23,1<s>71875</s> °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x02 || 2 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x03 || 3 |} Für die zweite Gruppe sieht die Nachricht wie folgt aus: <code> <span style="color: lightgrey"> 60 EF </span> <span class="hb1"> 1F 2F </span> <span class="hb2"> 60 00 </span> 00 <span class="hb3"> 4</span><span class="hb4">5 </span> <span style="color: lightgrey"> 0D 42 </span> <span style="color: lightgrey">01100000 11101111</span> <span class="hb1">00011111 00101111</span> <span class="hb2">01100000 00000000</span> 00000000 <span class="hb3">0100</span><span class="hb4">0101</span> <span style="color: lightgrey">00001101 01000010</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Temperatur A || x / 128 || 0x1F2F || 62,3<s>671875</s> °C |- | <code><span class="hb2">1.15:0</span></code> || Temperatur B || x / 128 || 0x6000 || 192 °C |- | <code><span class="hb3">2.7:4</span></code> || Index Temperatur A || x || 0x04 || 4 |- | <code><span class="hb4">2.3:0</span></code> || Index Temperatur B || x || 0x05 || 5 |} Index 1 und 2 konnten noch nicht beobachtet werden, Index 5 entspricht dem ungenutzten Eingang 4, der mit einem Widerstand terminiert ist. Dementsprechend ist davon auszugehen, dass die Indizes einfach um 2 verschoben sind. ===01F0: Außentemperatur=== <code> <span style="color: lightgrey"> 01 F0 </span> <span class="hb1"> 0A 06 </span> <span class="hb2"> 2</span>2 <span class="hb3"> </span> FA 00 00 <span style="color: lightgrey"> 0D 1D </span> <span style="color: lightgrey">00000001 11110000</span> <span class="hb1">00001010 00000110</span> 00<span class="hb2">10</span>00<span class="hb3">10</span> 11111010 00000000 00000000 <span style="color: lightgrey">00001101 00011101</span> <span style="color: lightgrey">!!!!!!!! !!!!!!!!</span> <span class="hb1">!!!!!!!! !!!!!!!!</span> ??<span class="hb2">!!</span>??<span class="hb3">!!</span> ???????? 00000000 00000000 <span style="color: lightgrey">00001101 !!!!!!!!</span> </code> {| class="wikitable" |- ! Position !! Bezeichnung !! Berechnung !! Wert aus Beispiel !! Berechnet |- | <code><span class="hb1">1.15:0</span></code> || Außentemperatur || x / 128 || 0x0A06 || 20,0<s>46875</s> °C |- | <code><span class="hb2">2.13:12</span></code> || Betriebsmodus Brauchwasserkreis || s. u. || 0x02 || Komforttemperatur |- | <code><span class="hb3">2.9:8</span></code> || Betriebsmodus Heizkreis || s. u. || 0x02 || Komforttemperatur |} Der Betriebsmodus wird vermutlich nach folgender Tabelle bestimmt: {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Reduzierte Temperatur |- | 01 || 1 || Optimierte Aufheizphase |- | 10 || 2 || Komforttemperatur |- | 11 || 3 || Optimierte Absenkphase |} Bisher habe ich nur Modus 0 und 2 gesehen, die anderen beiden stammen aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet. ===62FE: Setzen Relais an ECA 86=== <code> <span style="color: lightgrey"> 62 FE </span> FF FF FF FF 00 00 <span style="color: lightgrey"> 0D 5C </span> <span style="color: lightgrey">01100010 11111110</span> 11111111 11111111 11111111 11111111 00000000 00000000 <span style="color: lightgrey">00001101 01011100</span> </code> Da die Heizung während der Aufzeichnungen nie aktiv war, gibt es hierzu noch keine Informationen. ===Alarmmodul=== Das Alarmmodul ist leider nicht am ECL Bus (sondern am ECL 300) angeschlossen, auch konnte ich keine Nachrichten ausmachen, in dem ein etwaiger Alarmzustand übertragen wird. Dadurch ist die Ferndiagnose über den ECL-Bus leider in weite Ferne gerückt. =Downloads= *[[Datei:Ecl_bus_data.zip]] Aufzeichnungen (Saleae Logic 2.3.35), gefilterte, und gesparste Daten und Python-Scripts zum Filtern/Parsen. Bitte beachten: Die Aufzeichnungen in Logic sind invertiert [[Kategorie:Haustechnik]] [[Kategorie:Energieerfassung]] [[Kategorie:Reverse Engineering]] fc1380e68ef4f6ef97252a52ea1f8e796b9ec5d8 ECL-Bus-Decoder 0 225 1692 1261 2021-09-07T11:43:58Z Chris 2 Link auf [[ECL-Bus-Protokoll]] wikitext text/x-wiki '''Eine etwas andere Sichtweise und Aufarbeitung der Protokollanalyse kann dem Artikel [[ECL-Bus-Protokoll]] entnommen werden. Dieser Artikel wird archiviert, sobald alle Infos übertragen/aktualisiert wurden.''' Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: == Busteilnehmer == {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} === ECL 300 === [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Das/Der ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. Auf der Vorderseite befindet sich eine Diagnoseschnittstelle, die als RS232 mit 1200 Baud, 8 Bit, Odd Parity und 2 Stoppbits spricht. Der Stecker ist ein RJ12 (6P6C), die Anschlussbelegung für den PC lautet wie folgt: {| class="wikitable" |- ! RJ12 !! Sub-D |- | 4 Rx || 3 |- | 5 Tx || 2 |- | 7 GND || 5 |} Achtung: Die Zählweise beim RJ12-Stecker beginnt bei 2. Aufgrund der mäßigen Beschreibung im Datenblatt kann es sein, dass die Belegung gespiegelt ist (werde ich noch prüfen) Das Auslesen findet "aktiv" statt, d. h. man muss Werte abfragen - der Regler sendet von sich aus nichts. Zum Abfragen der Temperaturen muss man 0xCE <addr> 0x00 0x00 <checksum> senden. Für die Checksum muss man alle gesendeten Bytes ver-XOR-en, für die Temperaturen also einfach 0xCE ^ addr. {| class="wikitable" |- ! Adresse !! Anschluss |- | 0xFA || B8 |- | 0x32 || B5 |- | 0x34 || B4 ? |- | 0xF8 || B3 ? |- | 0xFC || B7 ? |- | 0x38 || B2 |- | 0x3C || B1 |} [http://de.fernwaerme.danfoss.com/xxTypex/17613_MNU17407525_SIT21.html Produktseite bei Danfoss] === ECA 86 === [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt [http://de.fernwaerme.danfoss.com/Product/087B1158_MNU17407526.html Produktseite bei Danfoss] === ECA 60 === [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEProm 93C66A (512x8 bit) gespeichert. [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407525.html Produktseite bei Danfoss] == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung !! Häufigkeit |- | AF || 04 || Innentemperatur (ECA 60) || 125/h |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || -- |- | AF || 09 || Abfrage Tagesprogramm || 63/h |- | AF || 11 || Zeit setzen || -- |- | EF || 60 || Temperaturfühler ECA 86 || 125/h |- | F0 || 01 || Außentemperatur || 125/h |- | F0 || 02 || Aktuelle Zeit || 125/h |- | FA || 05 || Solltemperatur am ECL 300 setzen || -- |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) || -- |- | FA || 09 || Tagesprogramm (Antwort auf AF06) || 63/h |- | FE || 62 || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine Stunde, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. Die Positionsangaben b[x] beziehen sich auf den 0-basierenden Index im Paket, die Angabe "das x-te Byte" auf die 1-basierende Position. Das Byte zu Beginn eines Pakets ist also b[0] und wird mit "1. Byte" bezeichnet. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 Temperatur </pre> Im 4. Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im dritten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[3] + b[2]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger (siehe Diagramm). === AF05/FA05/FF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? !!!!!!!0 !!!!!!!0 ?0000!!! Soltmp. Abw.tmp. Modus </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das dritte Byte (b[2]) bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. ==== Solltemperatur ==== Im 5. Byte befindet sich die Solltemperatur um ein Bit verschoben (b[3] >> 1). ==== Abweichende Temperatur ==== Im 6. bzw. 7. Byte ist die Abweichung zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gültig ist. Im Modus "Entspannen" wird die Abweichung in b[5] gespeichert, bei "Abwesenheit" in b[6]. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Um echte 8-Bit-Integer verwenden zu können, werden im Code die fehlenden Bits ersetzt: <pre> if(type == ECL_DIFF_RELAX) { ecl_data.tmp_diff = buff[5] >> 1; if(ecl_data.tmp_diff & 0x20) { ecl_data.tmp_diff |= 0xC0; } } else if(type == ECL_DIFF_AWAY) { ecl_data.tmp_diff = buff[6] >> 1; if(ecl_data.tmp_diff & 0x40) { ecl_data.tmp_diff |= 0x80; } } </pre> Das Setzen einer Abweichungen ist etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern. ==== Betriebsart ==== Das letzte (8.) Byte zeigt an, in welcher Betriebsart sich der Regler befindet. {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Handbetrieb |- | 001 || 1 || Zeitgesteuerter Betrieb |- | 010 || 2 || Konstante Komforttemperatur |- | 011 || 3 || Konstante reduzierte Temperatur |- | 100 || 4 || Standby |} Die restlichen möglichen Stati sind mir nicht bekannt. === AF06/FA06 (Bestätigung Solltemperatur) === Dieses Paket dient anscheinend der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (FA06 folgt auf AF05 bw. AF06 folgt auf FA05) direkt nach einem **05-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden. === AF09/FA09 (Tagesprogramm) === Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen. Um diese Daten zu erhalten, muss es folgendes auf den Bus legen: <pre> AF09 00000010 00000000 00000000 00000000 00000000 00000000 00000!!! 00000000 00000000 00000000 00000000 00000000 Tag </pre> Die untersten 3 Bit des dritten Byte entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6. Der ECL300 antwortet dann wie folgt: <pre> FA09 00001111 11111111 11111111 11111111 11110000 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ^ 23:30 00:00 ^ </pre> Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet. In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr. === AF11/F002 (Zeit setzen/Aktuelle Zeit) === <pre> F002 *** TODO *** 0!!!!!!! 0!!!!!!! 00!!!!!!! 00!!!!!! !!!!!!!! !!!!!!!! Sekunde Minute Stunde Tag Jahr WTagMona </pre> Die Uhrzeit ist einfacher aufgebaut, als man Denkt. In den Bytes folgen aufeinander die Sekunde (b[2]), Minute und Stunde des aktuellen Tags. Der aktuelle Tag wird im 6. Byte gespeichert, das 8. Byte enthält im höherwertigen Nibble den aktuellen Wochentag (TODO: welcher ist nochmal der erste?) und im niederwertigen den aktuellen Monat (1-12). Das Jahr (b[6]) ist relativ zum Jahr 1900 notiert. Um den "korrekten" Wert zu erhalten, muss man zu dem empfangenen Byte einfach 1900 addieren. === EF60 (Temperatursensoren ECA86) === <pre> EF60 10000001 00011110 01101000 00001001 00100011 00000000 EF60 01110101 00011111 00000000 01100000 01000101 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! 00000000 Temperatur Bx/x Temperatur Bx/x Index </pre> Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt. Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes nach der Adresse, der zweite in den beiden darauf folgenden. Das 7. Byte gibt an, um welche Werte es sich handelt. === F001 (Außentemperatur) === <pre> F001 *** TODO *** !!!!!!!! ?!!!!!!! ???????? !!!!!!!! ???????? ???????? Temperatur Modus </pre> In den beiden Bytes nach der Adresse steht - im gleichen Schema wie die Innentemperatur - Kodierte Außentemperatur. Im 6. Byte stehen die Modi für die beiden Heizkreise. Das die oberen 4 Bit repräsentieren hier den Brauchwasserkreis, die unteren 4 den Heizkreis. {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Reduzierte Temperatur |- | 01 || 1 || Optimierte Aufheizphase |- | 10 || 2 || Komforttemperatur |- | 11 || 3 || Optimierte Absenkphase |} Selbst miterlebt habe ich nur Modus 0 und 2, die anderen beiden entstanden aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet. Was mit den restlichen 12 möglichen Stati ist, weiß ich nicht. === FE62 (Setzen Relais an ECA 86) === == Prüfsumme == Wie bereits im [http://hobbyelektronik.org/b/?p=415 Blog] bemängelt ist die Prüfsumme nicht allzu solide. Sie wird berechnet, indem alle Bytes des Pakets exklusive der vorletzten beiden miteinander addiert (!) werden und mit 0xFF verundet werden. Diese "Prüfsumme" entspricht dem vorletzten Byte des Pakets, wobei es manchmal vorkommt, dass das MSB gekippt ist (näherer Grund ist noch unbekannt). Das letzte Paket im Byte ist immer 0x0D, was zur Synchronisierung verwendet werden kann. == Was fehlt noch? == === Störung === Seitdem ich die Daten erfasse hatte ich leider/zum Glück noch keine Störung der Anlage. Ich könnte sie zwar am Alarmmodul künstlich erzeugen, war bisher aber noch nicht mutig/dumm genug. Laut Installateur werden Störungen auf dem ECA60 angezeigt, deshalb liegt sehr nahe, dass diese auch über den Bus übertragen werden. === Aktives Auslesen === Dass das aktive Auslesen von Parametern funktioniert, zeigt das ECA 60 mit dem aktuellen Tagesprogramm. Geht das auch mit anderen Werten? = Firmware = {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = CB | FuseL = FD }} Die Firmware für AVRs (oder besser gesagt C-Code) belegt einen Pin- (INT0) und einen Timer-Interrupt (TIMER0), mit denen das Signal vom ECL-Bus gesampelt wird. Die ISRs hierfür können in jeder beliebigen C-Datei stehen. die aufgerufenen Funktionen werden vom Compiler inline eingefügt. Damit das ohne zusätzlichen Speicherplatz funktioniert, musste ich (da ich es zugegebenermaßen nicht besser weiß), den Code fürs Sampeln in die H-Datei des Decoders einfügen. (Wer eine bessere/richtige Methode kennt, ich freue mich über Feedback!) In der Main-Schleife des Programms muss zusätzlich ecl_decode() aufgerufen werden, welche das zuletzt empfangene Paket auswertet und in die Variable ecl_data schreibt. Die Funktion sollte alle 8-12ms aufgerufen werden, damit kein Paket verpasst wird. Hier könnte noch etwas Optimierungsbedarf bestehen. Die Praxis wird zeigen, wie (un)günstig die aktuelle Einlesemethode ist. Um flexibel zu bleiben, verwendet der Code einige Präprozessoranweisungen, über die die einzulesenden Daten sowie Speicherbelegung beeinflusst werden können. Über die Konfiguration kann auch das Debugging konfiguriert werden. Die Beschaltung ist - wie oben weiter oben zu lesen - sehr einfach. Der ECL-Bus wird über einen Optokoppler galvanisch getrennt. Der Kollektor des Optos wird über einen Pull-Up nach oben gezogen (der AVR-interne dürfte hierfür reichen, momentan wird ein externer vorausgesetzt) und das Signal an PD2 (INT0) weitergegeben. In der Standardkonfiguration lässt der Code nur eine an PD6/PD7 gegen Masse angeschlossene Duo-LED (Grün an PD6, Rot an PD7) je nach empfangenem Paket/Status kurz aufleuchten. Konkrete Daten erhält man, wenn man das rudimentäre Debugging aktiviert und am UART bei 19200 Baud 8N1 lauscht. = Download = [[Datei:ECLBus.zip]] Version 0.1, AVR-Studio-Projekt [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Reverse Engineering]] 317071799bb21dbf31548c885f285d7045411e09 1695 1692 2021-09-07T11:47:51Z Chris 2 Kategorie ergänzt wikitext text/x-wiki '''Eine etwas andere Sichtweise und Aufarbeitung der Protokollanalyse kann dem Artikel [[ECL-Bus-Protokoll]] entnommen werden. Dieser Artikel wird archiviert, sobald alle Infos übertragen/aktualisiert wurden.''' Da mir die Betriebsdatenerfassung unserer Wärmepumpe nicht ganz [[Energieerfassung#W.C3.A4rmepumpe|koscher]] war, hab ich diese Sache relativ schnell auf die Seite gelegt. Trotzdem hat es mir immer wieder in den Fingerspitzen gekribbelt, dem Gerät doch ein paar Kennwerte zu entlocken. Wie im Blog [http://hobbyelektronik.org/b/?p=386 erwähnt] bin ich durch einen (un)glücklichen Zufall an ein [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407524.html ECA60] von Danfoss gekommen. In der Bedienungsanleitung der Wärmepumpe entdeckte ich ein paar Schaltpläne, in denen ein externes Sensor-/Alarmmodul samt Busanbindung befindet, die auch an externe Klemmen geführt werden. Die Recherche nach dem mit ECL betitelte Bus lieferte bis auf ein paar kommerzielle Datenwandler keine Ergebnisse. Auch der Support von Danfoss selbst konnte/wollte keine Hilfestellung geben. = Interface = Um die Entwicklung eines Businterfaces zu vereinfachen, habe ich die Platine des Geräts fotografiert und per Bildbearbeitung übereinandergelegt: <gallery> Datei:ECL_ECA60-top.jpg|Oberseite Datei:ECL_ECA60-bot.jpg|Unterseite (gespiegelt) </gallery> Mit etwas Buntstift und Überlegen entstand in EAGLE folgender Stromlaufplan: <gallery> Datei:ECL-eca60-sch.png|Bus-Interface ECL-Bus </gallery> Oben wird das Bussignal eingefüttert, an der mittleren CPU-Leitung liegt das auf Vcc + ~0,7V begrenzte Signal, das vom Bus empfangen wird. Die obere und untere Leitung zur CPU dienen offensichtlich dem Senden auf dem Bus. Zuerst (siehe Historie des obigen Bildes) war ich etwas irritiert, warum T1 und T2 den Bus gegen sich selbst kurzschloss. Bis ich gesehen habe, dass dort ein Elko zur Spannungsglättung vorhanden ist. Das machte die Sache deutlich klarer: "Jeder" Teilnehmer im Bus sendet in den Low-Phasen des Trägersignals, indem er die "Restenergie" im Elko zum Senden verwendet. Über T3 kann der Bus (der übrigens mit knapp 27V getrieben wird) gegen GND gezogen werden. Zwar ergibt sich durch den Widerstand von 48kOhm nur ein Strom von 550µA, der dürfte aber reichen, Störeinflüsse bis zu einem gewissen Maß einzudämmen. = Messungen = Der Stromlaufplan lässt aufgrund fehlender Komperatoren/Filter/etc. vermuten, dass - anders als der [[VBus-Decoder|VBus]] er mit den Pegeln 0V/Busspannung arbeitet. Das Oszilloskop ist hier gleicher Meinung: <gallery> Datei:ECL-Oszi1.png|Ausschnitt eines Datenpakets Datei:ECL-Oszi2.png|Länge eines Bits </gallery> Das Signal besteht aus einem 50Hz Rechtecksignal, wobei der Duty-Cycle etwa 36/64 ist. Die Nutzinformationen werden in der Low-Phase des (ich nenne es einfach mal) Trägersignals übermittelt. Hier werden die Daten mit einer Bitlänge von ca. 428µs übertragen. Mit den gemessenen Werten kann man auf 16.8 Bit pro Teilpaket schließen. Da ich mit meinem Oszilloskop leider keinen vollständigen Datensatz einfangen konnte und die Messversuche mit einer Soundkarte auch nicht besser waren, wurde ein wirklich einfaches Interface - bestehend aus Widerständen und Optokoppler - gestrickt und an den Logic Analyzer angeschlossen. Nach einer Woche gespannter Leitung quer durchs Haus habe ich selbige durch Leerrohre gelegt. Aus der Toleranz der Familie wird Akzeptanz und der weiteren Bastelei steht nichts mehr im Weg ;-) Invertiert durch den Optokoppler kommen die Signale wie folgt am LA an: [[Datei:Ecl la1.png|800px]] Zu sehen ist ein komplettes Datenpaket - bestehend aus 5 Paketteilen. [[Datei:Ecl la2.png|800px]] Mit der Hilfe von ein paar Zeitmarken lassen sich die Parameter des PHY etwas genauer bestimmen: {| class="wikitable" |- | Bitdauer (T2-T1) || 0,415ms |- | Teilpaketlänge (T3-T1) || 7,26ms |- | Inaktiv-Phase (T4-T3) || 12,75ms |- | Periode (T4-T1) || 20,01ms |} Mit der Bit- und Teilpaketlänge kann nun wieder die Anzahl der Bits im Teilpaket berechnet werden. Unter Berücksichtigung von Jitter kommt man dabei auf 18 Bit, wobei das erste Bit zur Synchronisation immer 0 ist. = Protokollanalyse = == Hardware == Da mein Logic Analyzer nicht allzu viel Speicher hat und auch nicht auf den PC streamen kann, half ein AVR (Atmega8 mit 12MHz und [[Datei:Ecl protokollyse.c]]) etwas nach: INT0 löst bei einer steigenden Flanke auf dem Bus aus, deaktiviert sich selbst, löscht das zuletzt empfangene Teilpaket und aktiviert den Timer mit anderdhalb Bit Wartezeit, um ab dem zweiten empfangenen Bit (Sampling in der Mitte) zu lesen. Im ersten Versuch habe ich die Daten ab dem ersten Bit einlesen lassen, was im Nachhinein ein dummer Fehler war. Zwar konnte ich die Daten korrekt dekodieren, alle Daten waren natürlich um ein Bit verschoben, was aufgrund des stellenweise merkwürdigen Datenaufbau nicht aufgefallen ist. Im Timer0-Interrupt wird nun insgesamt 17 mal ausgelöst und schiebt jedes empfangene Bit in den Puffer. Beim 17. Bit wird der Timer deaktiviert und INT0 wieder aktiviert, sodass das nächste (Teil-)Paket empfangen werden kann. Im Main-Loop wird stetig geprüft, ob ein vollständiges Teilpaket empfangen wurde. Wenn dies der Fall ist, werden im Groben die empfangenen Daten hexadezimal ausgegeben. Genauer: da prinzipiell immer leere Datenpakete empfangen werden, wird geprüft, ob die ersten 8 Bit ungleich 0 ist. Ist dies der Fall, werden die nächsten 5 Teilpakete an auf dem UART ausgegeben. Damit wird die Ausgabe deutlich übersichtlicher und die Gefahr, Daten zu verlieren bleibt relativ gering. == Software == Auf der PC-Seite werkelt zunächst [http://www.der-hammer.info/terminal/ Hterm], das die Daten entgegennimmt. Der Ausgabe sieht in etwa wie folgt aus: <pre> 000000 000000 F00201 2C2001 141301 6F6301 370D01 000000 000000 000000 000000 AF0400 2F0A00 000000 000000 EC0D00 000000 000000 </pre> die 000000-Blöcke sind in Wahrheit meist deutlich länger, werden aber - wie oben beschrieben - von der Software im AVR gekürzt. Erwähnenswert ist an dieser Stelle vielleicht noch, dass das LSB (Least Significant Bit) zuerst übertragen wird, was in der AVR-Software bereits berücksichtigt wird. Wie man aus dem Auszug oben erahnen kann, bestehen die Pakete aus 5 Teilpaketen. Aus der blinden Annahme heraus, dass das erste wohl in irgendeiner Form einer Adresse entsprechen muss, habe ich das erste Teilpaket mehrerer Pakete genommen und in einem deutlich längeren (29000 Zeilen) Auszug suchen lassen. Ergebnis: diese Teilpakete wiederholen sich und stehen immer am Anfang eines Pakets - größtenteils periodisch. Beim weiteren Durchsuchen finden sich folgende Paketköpfe: AF0400, AF0500, AF0900, EF6000, F00101, F00201, FA0501, FA0601, FA0901 und FE6201. Auffällig ist hier bereits, dass die ersten beiden Zeichen (Nibbles) nur A, E, F und 0 sind, was schon fast nach Adressen schreit. Zudem ist das letzte empfangene Bit (dargestellt durch ein volles Byte, an der niedrigsten Stelle, da das LSB zuerst übertragen wird) 1, wenn das erste Nibble F ist. Allgemein lässt die Häufigkeit des F vermuten, dass es sich um die Adresse des Reglers handelt. Da eine blinde Analyse eher mühselig ist, galt es bekannte Werte zu verwenden oder diese einfach zu erzeugen. Über den ECA 60 kann man u. a. die Soll-Raum-Temperatur einstellen. Was liegt also näher, diese zu verändern und auf dem Bus zu lauschen: <pre> AF0500 FF2800 2A0000 000100 060D00 FA0601 002801 2AFF01 FF0101 510D01 AF0500 FF2A00 2A0000 000100 080D00 FA0601 002A01 2AFF01 FF0101 530D01 AF0500 FF2C00 2A0000 000100 0A0D00 FA0601 002C01 2AFF01 FF0101 550D01 AF0500 FF2E00 2A0000 000100 0C0D00 FA0601 002E01 2AFF01 FF0101 570D01 </pre> In dieser Sequenz wurde die Temperatur zuerst auf 20, dann auf 21, 22 und 23°C angehoben. Passend hierzu gibt es die Pakete mit den Adressen AF0500 und AF0601. Betrachtet man die Pakete einzeln, sieht man, dass sich (ungeachtet dem letzten Teilpaket) immer nur das zweite Byte im zweiten Paket ändert. Wie der Zufall will, entspricht dieser Wert im Dezimalsystem auch exakt dem, was auf dem Display steht. Durch den Paketverkehr kann man nun auch darauf schließen, dass das Raumleitgerät zuerst an den Regler sendet und dieser dann den gesetzten Wert bestätigt. Der Adresskopf folgt also dem Muster <Absender (4 Bit)><Empfänger (4 Bit)><Befehl (8 Bit)><Befehl vom Master (1 Bit)>. Warum im letzten Bit jedes Teilpakets immer übertragen wird, ob das aktuelle Paket vom Master stammt, habe ich bis jetzt noch nicht herausgefunden. Da die Information redundant ist, lasse ich sie im Folgenden außenvor. Nach näherer Analyse der Daten ergab sich folgende Geräteliste: == Busteilnehmer == {| class="wikitable" |- ! Adresse !! Bezeichnung |- | 0 || Broadcast |- | A || '''ECA 60''' Raumleitgerät |- | E || '''ECA 86''' Alarm- und Temperaturüberwachungsmodul |- | F || '''ECL 300''' Regler |} === ECL 300 === [[Datei:Ecl300.jpg|200px|thumb|ECL 300]] Das/Der ECL 300 ist das Herzstück der Heizungsanlage. Es übernimmt die Steuerung der Wärmepumpe und (qualitative?!) die Regelung der Raumtemperatur und lässt uns manchmal in der kalten Dusche stehen. Das Reglerprogramm - oder zumindest die Parameter hierfür - wird auf einer Smartcard gespeichert, ohne die die langfristige Bedienung nicht möglich ist. Damit kein "Cardsharing" möglich ist, wird/wurde als Schutzfunktion vor unbefugtem Verstellen vermarktet. Der Regler bietet Anschlussmöglichkeit für 5 Temperatursensoren (PT1000), ein Alarmmodul, schaltet 7 Ausgänge (3 Relais, 4 Triacs) und lässt sich über den hier beschriebenen Bus erweitern. Auf der Vorderseite befindet sich eine Diagnoseschnittstelle, die als RS232 mit 1200 Baud, 8 Bit, Odd Parity und 2 Stoppbits spricht. Der Stecker ist ein RJ12 (6P6C), die Anschlussbelegung für den PC lautet wie folgt: {| class="wikitable" |- ! RJ12 !! Sub-D |- | 4 Rx || 3 |- | 5 Tx || 2 |- | 7 GND || 5 |} Achtung: Die Zählweise beim RJ12-Stecker beginnt bei 2. Aufgrund der mäßigen Beschreibung im Datenblatt kann es sein, dass die Belegung gespiegelt ist (werde ich noch prüfen) Das Auslesen findet "aktiv" statt, d. h. man muss Werte abfragen - der Regler sendet von sich aus nichts. Zum Abfragen der Temperaturen muss man 0xCE <addr> 0x00 0x00 <checksum> senden. Für die Checksum muss man alle gesendeten Bytes ver-XOR-en, für die Temperaturen also einfach 0xCE ^ addr. {| class="wikitable" |- ! Adresse !! Anschluss |- | 0xFA || B8 |- | 0x32 || B5 |- | 0x34 || B4 ? |- | 0xF8 || B3 ? |- | 0xFC || B7 ? |- | 0x38 || B2 |- | 0x3C || B1 |} [http://de.fernwaerme.danfoss.com/xxTypex/17613_MNU17407525_SIT21.html Produktseite bei Danfoss] === ECA 86 === [[Datei:Eca86.jpg|200px|thumb|ECA 86]] Über das per Bus angebundene Alarm- und Temperaturüberwachungsmodul lassen sich 4 weitere Temperatursensoren anschließen und 2 Relais ansteuern. Es beinhaltet einen AT90LS8535 und zwei CD4051 (vermutlich zum Muxen der Temperatursensoren). Nähreres ist mir noch nicht bekannt [http://de.fernwaerme.danfoss.com/Product/087B1158_MNU17407526.html Produktseite bei Danfoss] === ECA 60 === [[Datei:Eca60.jpg|200px|thumb|ECA 60]] Über das Raumleitgerät ECA 60 wird die - in die Regelung einfließende - Raumtemperatur gemessen und angezeigt. Über das Gerät kann auch die Solltemperatur sowie Abwesenheit als auch Anwesenheit ("Komfortbetrieb") angegeben werden. Ferner lässt sich mit ihm die Uhrzeit des Reglers stellen (was bei der relativ starken Gangabweichung der internen Uhr sehr praktisch ist). Im Inneren arbeitet ein HD6473837 von Renesas, Daten werden in einem Atmel SPI-EEProm 93C66A (512x8 bit) gespeichert. [http://de.fernwaerme.danfoss.com/xxTypex/17616_MNU17407525.html Produktseite bei Danfoss] == Pakete == {| class="wikitable sortable" |- ! Sender/Empfänger !! Typ !! Bezeichnung !! Häufigkeit |- | AF || 04 || Innentemperatur (ECA 60) || 125/h |- | AF || 05 || Solltemperatur am ECA 60 setzen, Vorübergehende Wechsel (Freie Tage, Urlaub, Entspannen, Abwesenheit) || -- |- | AF || 09 || Abfrage Tagesprogramm || 63/h |- | AF || 11 || Zeit setzen || -- |- | EF || 60 || Temperaturfühler ECA 86 || 125/h |- | F0 || 01 || Außentemperatur || 125/h |- | F0 || 02 || Aktuelle Zeit || 125/h |- | FA || 05 || Solltemperatur am ECL 300 setzen || -- |- | FA || 06 || Bestätigung Setzen Solltemperatur (Antwort auf AF05) || -- |- | FA || 09 || Tagesprogramm (Antwort auf AF06) || 63/h |- | FE || 62 || Setzen Relais an ECA 86 || 125/h |} Die Häufigkeit bezieht sich auf eine Stunde, wobei es sich um ungefähre Werte handelt, da z. B. beim Starten/Stoppen der Wärmepumpe Relais-Befehle außerhalb des Zeitrasters gesendet werden. In den Codebeispielen ist unter dem Beispiel jeweils angegeben, welche Bits bekannt und dekodiert (!), unbekannt (?) und bei den bisherigen Daten immer 1 oder 0 waren. Die Positionsangaben b[x] beziehen sich auf den 0-basierenden Index im Paket, die Angabe "das x-te Byte" auf die 1-basierende Position. Das Byte zu Beginn eines Pakets ist also b[0] und wird mit "1. Byte" bezeichnet. === AF04 (Innentemperatur) === [[Datei:ECA60_Temperatur.PNG|200px|thumb|100 exemplarische Messwerte der Temperatur am ECA 60]] Die Innentemperatur wird nur übertragen, wenn ein ECA 60 angeschlossen ist. <pre> AF04 10101011 00001011 00000000 00000000 00000000 00000000 !!!!!!!! ?!!!!!!! 00000000 00000000 00000000 00000000 Temperatur </pre> Im 4. Byte wird der ganzzahlige Anteil der Temperatur um 1 Bit nach rechts verschoben ausgegeben. Das "fehlende" Bit befindet sich im dritten Byte an höchstwertiger Stelle. Die Temperatur kann mit der Formel b[3] + b[2]/128 berechnet. Im Beispiel wird eine der Wert 23,3359375°C übertragen. Die Anzahl der verwertbaren Stellen ist allerdings bedeutend niedriger (siehe Diagramm). === AF05/FA05/FF05 (Solltemperatur, ...) === <pre> AF05 11111111 00101010 00101000 00000000 11101100 10000011 ???????? 00!!!!!0 ???????? !!!!!!!0 !!!!!!!0 ?0000!!! Soltmp. Abw.tmp. Modus </pre> Mit diesem Paket kann das Raumleitgerät die Solltemperatur, Abwesenheit und Anwesenheit festlegen. Was das dritte Byte (b[2]) bedeutet, habe ich bis jetzt leider noch nicht herausfinden können. Was ich weiß ist, dass es manchmal komplett 0x00, meistens jedoch 0xFF enthält, wobei ich bis jetzt kein Muster erkennen konnte. ==== Solltemperatur ==== Im 5. Byte befindet sich die Solltemperatur um ein Bit verschoben (b[3] >> 1). ==== Abweichende Temperatur ==== Im 6. bzw. 7. Byte ist die Abweichung zur aktuellen Solltemperatur notiert, die für stundenweise Abweichungen gültig ist. Im Modus "Entspannen" wird die Abweichung in b[5] gespeichert, bei "Abwesenheit" in b[6]. Bei den Angaben muss beachtet werden, dass das Byte - wie bei der Solltemperatur - um ein Bit nach rechts verschoben ist. Da die Abweichung der Solltemperatur gleichermaßen positiv wie negativ sein kann, muss für negative Abweichungen das Zweierkomplement verwendet werden. Um echte 8-Bit-Integer verwenden zu können, werden im Code die fehlenden Bits ersetzt: <pre> if(type == ECL_DIFF_RELAX) { ecl_data.tmp_diff = buff[5] >> 1; if(ecl_data.tmp_diff & 0x20) { ecl_data.tmp_diff |= 0xC0; } } else if(type == ECL_DIFF_AWAY) { ecl_data.tmp_diff = buff[6] >> 1; if(ecl_data.tmp_diff & 0x40) { ecl_data.tmp_diff |= 0x80; } } </pre> Das Setzen einer Abweichungen ist etwas merkwürdig. Es wird anscheinend nicht übermittelt, wie lange die Abweichung gültig ist. Trotzdem "weiß" das Raumleitgerät nach dem Trennen und wieder Verbinden mit dem Bus noch, dass eine Abweichung stattgefunden hat und wie lange diese noch gültig ist. Meine Vermutung ist, dass die Abweichung im EEProm im ECA60 gespeichert wird (nicht verifiziert) und nach dem "Neustart" mit der vom Regler erhaltenen Zeit verrechnet wird. Fraglich ist (sofern meine Annahme richtig ist), wie der Regler reagiert, wenn das Raumleitgerät nach dem Setzen der vorübergehend abweichenden Solltemperatur vom Bus getrennt und nicht wieder angeschlossen wird. Ferner kann man sowohl bei Anwesenheit als auch bei Abwesenheit die abweichenden Temperaturen unsinnigerweise "verkehrt herum" belegen, also z. B. +5°C bei Abwesenheit oder -10°C bei Anwesenheit. Die einzige Unterscheidung darin liegt, dass die An-/Abwesenheit den Komfort- bzw. reduzierten Betrieb im Regler steuert und die Wunschtemperaturen unabhängig voneinander im Raumleitgerät gespeichert werden. Im Beispiel wird die Solltemperatur auf 21°C mit -10°C (also Solltemperatur 11°C) als kurzfristige Änderung gespeichert. Der Modus wird hierbei auf konstant reduzierte Temperatur gesetzt. Während der aktiven Sonderzeit ist das Verändern der Solltemperatur am ECL300 nicht möglich. Nur das Umschalten des Betriebsmodus z. B. von Automatik auf Manuell beendet die Sonderzeit und lässt die Solltemperatur wieder an beiden Geräten verändern. ==== Betriebsart ==== Das letzte (8.) Byte zeigt an, in welcher Betriebsart sich der Regler befindet. {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 000 || 0 || Handbetrieb |- | 001 || 1 || Zeitgesteuerter Betrieb |- | 010 || 2 || Konstante Komforttemperatur |- | 011 || 3 || Konstante reduzierte Temperatur |- | 100 || 4 || Standby |} Die restlichen möglichen Stati sind mir nicht bekannt. === AF06/FA06 (Bestätigung Solltemperatur) === Dieses Paket dient anscheinend der Bestätigung der gesetzten Solltemperatur, da es immer vom jeweilig anderen Gerät (FA06 folgt auf AF05 bw. AF06 folgt auf FA05) direkt nach einem **05-Paket gesendet wird. Weitere Informationen konnte ich in diesem Paket noch nicht finden. === AF09/FA09 (Tagesprogramm) === Das Raumleitgerät kann das aktuell gültige Tagesprogramm für den Heizkreis abfragen. Um diese Daten zu erhalten, muss es folgendes auf den Bus legen: <pre> AF09 00000010 00000000 00000000 00000000 00000000 00000000 00000!!! 00000000 00000000 00000000 00000000 00000000 Tag </pre> Die untersten 3 Bit des dritten Byte entsprechen dem Index des Wochentags, wobei gilt: Montag = 0, Dienstag = 1, ..., Sonntag = 6. Der ECL300 antwortet dann wie folgt: <pre> FA09 00001111 11111111 11111111 11111111 11110000 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ^ 23:30 00:00 ^ </pre> Dabei entspricht jedes Bit einer halben Stunde, wobei die Folge von rechts aus binär betrachtet mit 0:00 beginnt und links mit dem 23:30 endet. In diesem Beispiel beginnt die Komfort-Zeit für Dienstag um 6:00 und dauert bis 22:00 Uhr. === AF11/F002 (Zeit setzen/Aktuelle Zeit) === <pre> F002 *** TODO *** 0!!!!!!! 0!!!!!!! 00!!!!!!! 00!!!!!! !!!!!!!! !!!!!!!! Sekunde Minute Stunde Tag Jahr WTagMona </pre> Die Uhrzeit ist einfacher aufgebaut, als man Denkt. In den Bytes folgen aufeinander die Sekunde (b[2]), Minute und Stunde des aktuellen Tags. Der aktuelle Tag wird im 6. Byte gespeichert, das 8. Byte enthält im höherwertigen Nibble den aktuellen Wochentag (TODO: welcher ist nochmal der erste?) und im niederwertigen den aktuellen Monat (1-12). Das Jahr (b[6]) ist relativ zum Jahr 1900 notiert. Um den "korrekten" Wert zu erhalten, muss man zu dem empfangenen Byte einfach 1900 addieren. === EF60 (Temperatursensoren ECA86) === <pre> EF60 10000001 00011110 01101000 00001001 00100011 00000000 EF60 01110101 00011111 00000000 01100000 01000101 00000000 !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! 00000000 Temperatur Bx/x Temperatur Bx/x Index </pre> Die Messwerte werden hierbei wie bei der Innentemperatur übertragen - mit dem Unterschied, dass jedes Paket 2 Temperaturwerte trägt. Der erste Temperaturwert des jeweiligen Pakets steckt in den beiden Bytes nach der Adresse, der zweite in den beiden darauf folgenden. Das 7. Byte gibt an, um welche Werte es sich handelt. === F001 (Außentemperatur) === <pre> F001 *** TODO *** !!!!!!!! ?!!!!!!! ???????? !!!!!!!! ???????? ???????? Temperatur Modus </pre> In den beiden Bytes nach der Adresse steht - im gleichen Schema wie die Innentemperatur - Kodierte Außentemperatur. Im 6. Byte stehen die Modi für die beiden Heizkreise. Das die oberen 4 Bit repräsentieren hier den Brauchwasserkreis, die unteren 4 den Heizkreis. {| class="wikitable" |- ! Bin !! Dez !! Bedeutung |- | 00 || 0 || Reduzierte Temperatur |- | 01 || 1 || Optimierte Aufheizphase |- | 10 || 2 || Komforttemperatur |- | 11 || 3 || Optimierte Absenkphase |} Selbst miterlebt habe ich nur Modus 0 und 2, die anderen beiden entstanden aus Ableitung aus dem Datenblatt zum ECA 71, das seine Daten anscheinend auch vom ECL-Bus bezieht oder zumindest die gleiche Definition verwendet. Was mit den restlichen 12 möglichen Stati ist, weiß ich nicht. === FE62 (Setzen Relais an ECA 86) === == Prüfsumme == Wie bereits im [http://hobbyelektronik.org/b/?p=415 Blog] bemängelt ist die Prüfsumme nicht allzu solide. Sie wird berechnet, indem alle Bytes des Pakets exklusive der vorletzten beiden miteinander addiert (!) werden und mit 0xFF verundet werden. Diese "Prüfsumme" entspricht dem vorletzten Byte des Pakets, wobei es manchmal vorkommt, dass das MSB gekippt ist (näherer Grund ist noch unbekannt). Das letzte Paket im Byte ist immer 0x0D, was zur Synchronisierung verwendet werden kann. == Was fehlt noch? == === Störung === Seitdem ich die Daten erfasse hatte ich leider/zum Glück noch keine Störung der Anlage. Ich könnte sie zwar am Alarmmodul künstlich erzeugen, war bisher aber noch nicht mutig/dumm genug. Laut Installateur werden Störungen auf dem ECA60 angezeigt, deshalb liegt sehr nahe, dass diese auch über den Bus übertragen werden. === Aktives Auslesen === Dass das aktive Auslesen von Parametern funktioniert, zeigt das ECA 60 mit dem aktuellen Tagesprogramm. Geht das auch mit anderen Werten? = Firmware = {{Infobox AVR | Typ = ATmega8 | Takt = 12 | FuseH = CB | FuseL = FD }} Die Firmware für AVRs (oder besser gesagt C-Code) belegt einen Pin- (INT0) und einen Timer-Interrupt (TIMER0), mit denen das Signal vom ECL-Bus gesampelt wird. Die ISRs hierfür können in jeder beliebigen C-Datei stehen. die aufgerufenen Funktionen werden vom Compiler inline eingefügt. Damit das ohne zusätzlichen Speicherplatz funktioniert, musste ich (da ich es zugegebenermaßen nicht besser weiß), den Code fürs Sampeln in die H-Datei des Decoders einfügen. (Wer eine bessere/richtige Methode kennt, ich freue mich über Feedback!) In der Main-Schleife des Programms muss zusätzlich ecl_decode() aufgerufen werden, welche das zuletzt empfangene Paket auswertet und in die Variable ecl_data schreibt. Die Funktion sollte alle 8-12ms aufgerufen werden, damit kein Paket verpasst wird. Hier könnte noch etwas Optimierungsbedarf bestehen. Die Praxis wird zeigen, wie (un)günstig die aktuelle Einlesemethode ist. Um flexibel zu bleiben, verwendet der Code einige Präprozessoranweisungen, über die die einzulesenden Daten sowie Speicherbelegung beeinflusst werden können. Über die Konfiguration kann auch das Debugging konfiguriert werden. Die Beschaltung ist - wie oben weiter oben zu lesen - sehr einfach. Der ECL-Bus wird über einen Optokoppler galvanisch getrennt. Der Kollektor des Optos wird über einen Pull-Up nach oben gezogen (der AVR-interne dürfte hierfür reichen, momentan wird ein externer vorausgesetzt) und das Signal an PD2 (INT0) weitergegeben. In der Standardkonfiguration lässt der Code nur eine an PD6/PD7 gegen Masse angeschlossene Duo-LED (Grün an PD6, Rot an PD7) je nach empfangenem Paket/Status kurz aufleuchten. Konkrete Daten erhält man, wenn man das rudimentäre Debugging aktiviert und am UART bei 19200 Baud 8N1 lauscht. = Download = [[Datei:ECLBus.zip]] Version 0.1, AVR-Studio-Projekt [[Kategorie:Haustechnik]] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Reverse Engineering]] ea28e92946a39cd5c3ede969362f6e7db556710c Hauptseite 0 1 1694 1669 2021-09-07T11:46:13Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *07.09.2021 Eine aktualisierte Untersuchung des [[ECL-Bus-Protokoll]]s *12.07.2021 Der Pythoncode der [[MCP-USB-Bridge]] ist auf GitHub umgezogen und spricht nun mit dem MCP2210 (SPI) *26.02.2021 Und noch ein Update für den VBus-Decoder: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]] und [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]], sowie einem einfachen [[VBus-Decoder#Protokoll-Analysator|Protokoll-Analysator]] *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> 8255e87bc4fd4a94b70938b09936a3b7e5ce4f4b 1725 1694 2021-12-13T20:52:18Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *13.12.2021 Mal wieder ein VBus-Decoder - jetzt für den [[VBus-Decoder/Adapter_für_den_ESP8266|ESP8266]] *07.09.2021 Eine aktualisierte Untersuchung des [[ECL-Bus-Protokoll]]s *12.07.2021 Der Pythoncode der [[MCP-USB-Bridge]] ist auf GitHub umgezogen und spricht nun mit dem MCP2210 (SPI) *26.02.2021 Und noch ein Update für den VBus-Decoder: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]] und [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]], sowie einem einfachen [[VBus-Decoder#Protokoll-Analysator|Protokoll-Analysator]] *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> 8ed2d43c1b3700af89317ca55266019eea90eb0d Hobbyelektronik.org:Impressum 4 4 1698 1645 2021-10-06T19:11:20Z Chris 2 /* Verschlüsselung */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org For those who don't speak German: feel free to write me in English! Im Normalfall antworte ich innerhalb von 1-3 Tagen. Solltest du innerhalb einer Woche keine Antwort bekommen, prüfe bitte deinen Spamfilter oder schicke eine Erinnerung, manchmal geht auch bei mir etwas unter. E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung im Schnitt nur eine Konversation in 2-3 Jahren verschlüsselt stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Kommerzielle Anfragen= In den meisten Fällen lautet die Antwort schlicht "Nein". Wie weiter unten steht habe ich kein Interesse an Werbung oder "kommerzieller Kooperation". Entsprechende Anfragen werden ignoriert. Auch habe ich wenig Interesse, in meiner Freizeit an kommerziellen Projekten oder Produkten zu arbeiten. Dazu fehlen mir einfach Zeit und Ressourcen. Nicht unbedingt technisch, sondern vielmehr organisatorisch. Produkte auf den Markt zu bringen ist deutlich mehr als Hardware zusammenzuklatschen und vielleicht noch "ein bisschen" Software dafür zu entwickeln. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schneller (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzübung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nichts durch finanzielle Mittel beeinflusst. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich, kann aber zu Darstellungsfehlern führen. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) e8cbfee22eb54eb1733217920ba93bd6fd40c181 VBus-Decoder 0 120 1699 1662 2021-12-11T21:43:30Z Chris 2 /* Weblinks */ Link auf Github korrigiert wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Achtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] Oliver hat basierend auf dem Code von Nicki eine Schnittstelle zur [https://www.volkszaehler.org/ Volkszähler]-Middleware gebaut: <pre> Der Code nutzt die Resol-Decoder-Lib von Nicki, die ist auch mit dabei. In der config.py stellt man die Adresse der Middleware in seinem Netzwerk, sowie die UUID der Kanäle ein, damit man die Daten referenzieren kann. (Zum Test kann man auch simulierte Daten nutzen, oder die Ausgabe in ein File schreiben lassen) </pre> * [[Datei:Vbus_volkszaehler.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 25ff015a1ee48259469403268eb8ac0ce13843f7 1723 1699 2021-12-13T20:50:45Z Chris 2 /* Hardware */ Adapter für den ESP8266 hinzugefügt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Achtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter für den ESP8266|Adapter für den ESP8266]] Noch etwas kleiner als für den Raspberry Pi: Ein Adapter mit ESP8266-Modulen. <gallery> vbusesp_top.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] Oliver hat basierend auf dem Code von Nicki eine Schnittstelle zur [https://www.volkszaehler.org/ Volkszähler]-Middleware gebaut: <pre> Der Code nutzt die Resol-Decoder-Lib von Nicki, die ist auch mit dabei. In der config.py stellt man die Adresse der Middleware in seinem Netzwerk, sowie die UUID der Kanäle ein, damit man die Daten referenzieren kann. (Zum Test kann man auch simulierte Daten nutzen, oder die Ausgabe in ein File schreiben lassen) </pre> * [[Datei:Vbus_volkszaehler.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] f46bcfc95fd7860f9a4bdd7b42012a277000f8d9 1724 1723 2021-12-13T20:51:05Z Chris 2 /* Adapter für den Raspberry Pi */ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/vbus-packets.html Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Achtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter für den ESP8266|Adapter für den ESP8266]]== Noch etwas kleiner als für den Raspberry Pi: Ein Adapter mit ESP8266-Modulen. <gallery> vbusesp_top.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] Oliver hat basierend auf dem Code von Nicki eine Schnittstelle zur [https://www.volkszaehler.org/ Volkszähler]-Middleware gebaut: <pre> Der Code nutzt die Resol-Decoder-Lib von Nicki, die ist auch mit dabei. In der config.py stellt man die Adresse der Middleware in seinem Netzwerk, sowie die UUID der Kanäle ein, damit man die Daten referenzieren kann. (Zum Test kann man auch simulierte Daten nutzen, oder die Ausgabe in ein File schreiben lassen) </pre> * [[Datei:Vbus_volkszaehler.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 42d4b414c03e94323e6549be589db5851ea80bd6 Datei:Vbusesp 0.2.zip 6 735 1700 2021-12-13T20:44:59Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp optiso sch 2.png 6 736 1701 2021-12-13T20:45:00Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp direct sch 2.png 6 737 1702 2021-12-13T20:45:00Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp max sch 2.png 6 738 1703 2021-12-13T20:45:00Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp direct sch 1.png 6 739 1704 2021-12-13T20:45:00Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp optisonoesp sch 1.png 6 740 1705 2021-12-13T20:45:00Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp optisonoesp sch 2.png 6 741 1706 2021-12-13T20:45:00Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp max sch 1.png 6 742 1707 2021-12-13T20:45:00Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp optiso sch 1.png 6 743 1708 2021-12-13T20:45:00Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp vbusonly pinout.png 6 744 1709 2021-12-13T20:47:06Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp txjumper.png 6 745 1710 2021-12-13T20:47:06Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp vregsmps sch 1.png 6 746 1711 2021-12-13T20:47:06Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp prog 1.png 6 747 1712 2021-12-13T20:47:06Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp vregldo sch 1.png 6 748 1713 2021-12-13T20:47:07Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp vregldo assy.png 6 749 1714 2021-12-13T20:47:07Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp optisonoesp assy.png 6 750 1715 2021-12-13T20:47:07Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp prog 2.jpg 6 751 1716 2021-12-13T20:47:07Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp direct assy.png 6 752 1717 2021-12-13T20:47:07Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp optiso assy.png 6 753 1718 2021-12-13T20:47:07Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp top.jpg 6 754 1719 2021-12-13T20:47:07Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp max assy.png 6 755 1720 2021-12-13T20:47:07Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp vregsmps assy.png 6 756 1721 2021-12-13T20:47:07Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder/Adapter für den ESP8266 0 757 1722 2021-12-13T20:47:59Z Chris 2 Seite erstellt wikitext text/x-wiki [[Bild:vbusesp_top.jpg|thumb|Aufgebauter Leiterkarte (v0.1)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Wenn die Basteln und IoT aufeinandertreffen, kommt man fast nicht an den Mikrocontrollern von Espressif vorbei. Genau aus diesem Grund hatte ich schon länger die Idee, ein Leiterkärtchen mit dem ESP8266 zu machen. Also warum nicht einfach den beliebten VBus ohne großes Strippenziehen ins Netzwerk bringen? =Schaltung= Die Schaltung für den VBus basiert auf der für den [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Raspi (v1.3)]], aufseiten des ESP habe ich mich von den verschiedenen Bastelboards inspirieren lassen und die Möglichkeit vorgesehen, sowohl die kleinen ESP01- als auch die etwas vielseitigeren ESP12-Module einzusetzen. Die Versorgung findet über eine Stiftleiste (bzw. angelötete Drähte) oder über eine Micro-USB-Buchse statt. Diese dient nur der Stromversorgung - mehr zum Programmieren des ESP weiter unten. Bei der Verwendung des ESP12-Moduls stehen zusätzlich zum VBus-Interface noch die GPIOs 12, 13, 14 und 16 sowie der ADC-Eingang und die 3,3V-Versorgung zur Verfügung. Hier kann weitere Peripherie wie Sensoren oder Displays angeschlossen werden. Für den Aufbau gibt es mehrere Varianten, die unten aufgeführt sind. Diese können über die Tabs ausgewählt und müssen beim Besorgen der Bauteile und selbstverständlich beim Zusammenbau kombiniert werden. Die theoretische Maximalbestückung sieht wie folgt aus: <gallery> vbusesp_max_sch_1.png | Schaltplan VBus + Stromversorgung vbusesp_max_sch_2.png | Schaltplan ESP8266 und IO vbusesp_max_assy.png | Bestückungsplan </gallery> =BOM= Möglichkeiten schaffen Komplexität. Wie bei den anderen Plattformen lässt sich der Adapter in verschiedenen Varianten aufbauen, wobei ich (auch wenn es gerade bei dieser anbietet) noch immer empfehle, die Optoisolierte aufzubauen. ==Decoder== Neben Optoisoliert und Direkt gibt es noch die Variante ohne ESP - dank der Stiftleiste rechts oben auf der Leiterkarte lässt sich der VBus-Anteil komplett unabhängig vom ESP-Anteil verwenden. Mit Säge und Fingerspitzengefühl lässt sich die Größe auch noch ein gutes Stück reduzieren. Als ESP8266-Modul kann das ESP01 und ESP12(-F) verwendet werden. Getestet wurde bis jetzt nur das ESP12-F, wobei nichts gegen das 01 sprechen dürfte. <tabs> <tab name="Optoisoliert"> Empfohlene Bestückungsvariante. <gallery> vbusesp_optiso_sch_1.png | Variantenschaltplan VBus vbusesp_optiso_sch_2.png | Variantenschaltplan ESP8266 vbusesp_optiso_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R18, R19, R22 || 10k || R0805 || RND 0805 1 10K |- | 1 || R24 || 10k || R0805 || RND 0805 1 100 |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 3 || R20, R21, R25 || 1k || R0805 || RND 0805 1 1k |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Direkt"> <gallery> vbusesp_direct_sch_1.png | Variantenschaltplan VBus vbusesp_direct_sch_2.png | Variantenschaltplan ESP8266 vbusesp_direct_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R18, R19, R22 || 10k || R0805 || RND 0805 1 10K |- | 1 || R24 || 10k || R0805 || RND 0805 1 100 |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 3 || R20, R21, R25 || 1k || R0805 || RND 0805 1 1k |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 2 || Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Optoisoliert (ohne ESP)"> Wer keinen ESP8266 verwenden aber die Vorzüge der verbesserten Schaltung haben möchte, kann den ESP-Anteil vollständig weglassen. Hierfür wird auf dieser Leiterkarte keine Stromversorgung benötigt, da diese vom jeweilig verwendeten Interface (z. B. SBC, USB-UART-Wandler, ...) bezogen werden kann. <gallery> vbusesp_optisonoesp_sch_1.png | Variantenschaltplan VBus vbusesp_optisonoesp_sch_2.png | Variantenschaltplan Interface vbusesp_optisonoesp_assy.png | Bestückungsplan vbusesp_vbusonly_pinout.png | Anschlussbelegung des UART </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> ==Stromversorgung== Für die Stromversorgung gibt es ebenfalls zwei Möglichkeiten: Entweder mit LDO oder Schaltwandler. Wer auf Nummer sicher gehen will, nimmt die billigere LDO-Variante, da ich noch keine Gelegenheit hatte letztere zu testen. Die etwas höhere Stromaufnahme dürfte wahrscheinlich nicht allzu sehr ins Gewicht fallen. <tabs> <tab name="Linearregler"> Empfohlene Bestückungsvariante. <gallery> vbusesp_vregldo_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregldo_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || REG1117 || SOT223 || NCP 1117 ST33T3G |} </tab> <tab name="Schaltwandler"> <gallery> vbusesp_vregsmps_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregsmps_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C9 || 100n || C0603 || X7R-G0603 100N |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C12 || 10p || C0603 || NPO-G0603 10P |- | 1 || R17 || 15k || R0603 || RND 0603 1 15K |- | 1 || L1 || 15u || 242408FPS || L-242408FPS 15µ |- | 1 || R16 || 47k || R0603 || RND 0603 1 47K |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || D6 || BAT43WS || SOD323-W || BAT 43WS |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || IC2 || MCP16301 || SOT23-6 || MCP 16301T-I/CHY |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || D4 || SS13L || SUBSMA || SS 13L |} </tab> </tabs> =Inbetriebnahme/Benutzung= ==Flashing== Wird ein ESP8266 verwendet, muss natürlich erst einmal die Software auf den Mikrocontroller. Das Problem: Der Softwaredownload findet über den selben UART statt, der auch für das VBus-Interface statt. Nun könnte man mit Multiplexern arbeiten, was im Idealfall nur einmal benutzt werden würde und somit mit Kanonen auf Spatzen geschossen wäre. Aus den gleichen Grund gibt es keinen USB-UART-Konverter auf dem Board: Braucht nur Platz und kostet. Deshalb wird für das erstmalige Flashen ein USB-UART-Adapter, der RTS/DTR anbietet, benötigt. Dieser sollte idealerweise mit 3,3 V arbeite, wobei der ESP wohl auch 5 V toleriert. Die beiden Transistoren für Reset und Bootloader nach WittyCloud/NodeMCU sind bereits vorhanden. Die 5 V-Stromversorgung muss entweder über den USB-Port oder der Stiftleiste SV2 kommen, die Anschlussbelegung des UART an SV4 ist wie folgt: {| class="wikitable" ! Pin || Signal vom UART-Adapter |- | 1 || DTR |- | 3 || TX |- | 7 || RX |- | 9 || RTS |} <gallery> vbusesp_prog_1.png | Anschlussbelegung für das Programmieren per UART vbusesp_prog_2.jpg | Verwendung des WittyCloud-USB-Wandlers </gallery> Liegt das Trägerboard eines WittyCloud herum, müssen DTR und RTS gefädelt werden. ==Betrieb== Ist die Firmware auf dem Chip und es sollen Daten vom VBus decodiert werden, muss ein Jumper zwischen Pin 3 und 4 an SV4 oder ein Lötpunkt auf SJ1 gesetzt werden: <gallery> vbusesp_txjumper.png | UART-Verbindung zwischen VBus und ESP8266 </gallery> =Firmware= Zugegebenermaßen: ich habe zwar seit Jahren ein paar ESP8266-Module herumliegen, mich aber nie so richtig damit auseinandergesetzt. Aber das macht nichts: [https://tasmota.github.io/docs/ Tasmota] unterstützt verschiedene [https://tasmota.github.io/docs/Smart-Meter-Interface/ Smart Metering]-Anbindungen, für die die Firmware allerdings angepasst selbst kompiliert werden muss. Michael hat sich (mit der Unterstützung aus der Tasmota-Community) daran gemacht und freundlicherweise die nötigen Anpassungen zur Verfügung gestellt: Folgendes muss in der Datei <code>tasmota/user_config_override.h</code> ergänzt werden: <source lang="C"> #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ #ifndef USE_SCRIPT #define USE_SCRIPT #endif #ifndef USE_SML_M #define USE_SML_M #endif #ifdef USE_RULES #undef USE_RULES #endif #ifndef SML_REPLACE_VARS #define SML_REPLACE_VARS #endif #ifndef USE_SML_SCRIPT_CMD #define USE_SML_SCRIPT_CMD #endif #ifndef SML_MAX_VARS #define SML_MAX_VARS 20 #endif #ifndef USE_SCRIPT_JSON_EXPORT #define USE_SCRIPT_JSON_EXPORT #endif #ifndef USE_SCRIPT_WEB_DISPLAY #define USE_SCRIPT_WEB_DISPLAY #endif </source> Nach dem Flashen des Mikrocontrollers, was für fertige Builds auch über den Tasmotizer erfolgen kann, kann unter <code>Main-Menu -> Console -> Edit Script</code> das [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus Script ergänzt] werden. Mit dem Befehl <code>sensor53 d1</code> kann man den Header für die [https://tasmota.github.io/docs/Smart-Meter-Interface/#meter-metrics Meter Metrics] ermitteln und im Script entsprechend anpassen. Für die RemaSol B/2 sieht das wie folgt aus: <source> r="1,aa10005d101000010a67" coltemp=0 Byte1=0 Byte2=0 >S coltemp=sml[1] Byte1=coltemp>>8 Byte2=coltemp&0xff if Byte1==0x00 { coltemp=coltemp&0xff } if Byte1==0xff { coltemp=(coltemp-0x10000) } coltemp=coltemp*0.1 >B =>sensor53 r >M 1 +1,3,v,0,9600,Solar %r%vo0uw@1,KollektorBase,°C,kolbase,2 %r%vo0uw@10,KollektorOrg,°C,kolorg,2 %r%vo2uw@10,Speicher unten,°C,spu,1 %r%vo4uw@10,Speicher oben,°C,spo,1 %r%vo8ub@1,Pumpe,%%,pump,0 # >J ,"Calculated":{"kol":%coltemp%} >W Kollektor berechnet: {m} %coltemp% °C </source> Anmerkung: Hierbei handelt es sich um einen direkten Copy & Paste aus Michaels Script. Je nach Konfiguration der Anlage kann es Abweichungen geben. Um den Fragen zuvorzukommen - die Anpassung auf die Jeweilige Anlage beginnt in der ersten Zeile: <code> r="1,<span class="hb1">aa</span><span class="hb2">1000</span><span class="hb3">5d10</span><span class="hb4">10</span><span class="hb5">0001</span><span class="hb6">0a</span><span class="hb7">67</span>" </code> Die Farben entsprechen dem Beispiel von der [[VBus-Decoder#Protokoll|Artikelhauptseite]], kurzum: * <span class="hb1">aa</span>: Sync-Wort * <span class="hb2">1000</span>: Zieladresse * <span class="hb3">5d10</span>: Quelladresse * <span class="hb4">10</span>: Protokollversion * <span class="hb5">0001</span>: Befehl * <span class="hb6">0a</span>: Anzahl Nutzdatenframes * <span class="hb7">67</span>: Prüfsumme Die <span class="hb3">Quelladresse</span> kann in der [https://danielwippermann.github.io/resol-vbus/#/vsf VBus-Spezifikation nachgeschlagen werden]. Zu beachten ist hier die Endianness: was in der Doku als <code>0x1234</code> geschrieben ist, muss hier als <code>3412</code> angegeben werden. Anschließend muss man auf der [https://danielwippermann.github.io/resol-vbus/#/vsf oben genannten Seite] nach dem Command 0x0100 für den entsprechenden Regler suchen. Dazu am besten oben nach 0x0100 filtern und dann mit Strg+F die Quelladresse finden. Klickt man in der Zeile auf <code>Bytes</code> bekommt man die Länge der Nachricht, wobei man 1 addieren muss, da es sich um Offsets handelt. Beim RemaSol 1/2 (bzw. DeDietrich Sol Plus ER 709) ist der größte Offset 39, also 40 Bytes. Mit dem Wissen, dass ein Frame 4 Byte enthält, ergibt sich eine Länge von 10 Frames, was einem Hexadezimalwert von <span class="hb6">0x0A</span> entspricht. Nun muss man nur noch die Prüfsumme berechnen (oder durch Schnüffeln am UART ermitteln) Für die Feldzuordnung lohnt sich ein scharfer Blick und Vergleich der <code>Fields</code>-Seite für die [https://danielwippermann.github.io/resol-vbus/#/vsf/fields/00_0010_4221_10_0100 DeltaSol BS Plus] und dem Beispiel in der [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus dieses Reglers] in der Tasmota-Doku. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. Achtung: Es handelt sich um Version 0.1, auf der sich 3 kleine Fehler befinden, die sich allerdings mit Fädeldraht korrigieren lassen. =Downloads= * [[Datei:Vbusesp_0.2.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:ESP8266]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] b2fb8833a664cf179ca21d64e416d6939c5cb47c 1726 1722 2021-12-13T20:53:09Z Chris 2 /* Firmware */ wikitext text/x-wiki [[Bild:vbusesp_top.jpg|thumb|Aufgebauter Leiterkarte (v0.1)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Wenn die Basteln und IoT aufeinandertreffen, kommt man fast nicht an den Mikrocontrollern von Espressif vorbei. Genau aus diesem Grund hatte ich schon länger die Idee, ein Leiterkärtchen mit dem ESP8266 zu machen. Also warum nicht einfach den beliebten VBus ohne großes Strippenziehen ins Netzwerk bringen? =Schaltung= Die Schaltung für den VBus basiert auf der für den [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Raspi (v1.3)]], aufseiten des ESP habe ich mich von den verschiedenen Bastelboards inspirieren lassen und die Möglichkeit vorgesehen, sowohl die kleinen ESP01- als auch die etwas vielseitigeren ESP12-Module einzusetzen. Die Versorgung findet über eine Stiftleiste (bzw. angelötete Drähte) oder über eine Micro-USB-Buchse statt. Diese dient nur der Stromversorgung - mehr zum Programmieren des ESP weiter unten. Bei der Verwendung des ESP12-Moduls stehen zusätzlich zum VBus-Interface noch die GPIOs 12, 13, 14 und 16 sowie der ADC-Eingang und die 3,3V-Versorgung zur Verfügung. Hier kann weitere Peripherie wie Sensoren oder Displays angeschlossen werden. Für den Aufbau gibt es mehrere Varianten, die unten aufgeführt sind. Diese können über die Tabs ausgewählt und müssen beim Besorgen der Bauteile und selbstverständlich beim Zusammenbau kombiniert werden. Die theoretische Maximalbestückung sieht wie folgt aus: <gallery> vbusesp_max_sch_1.png | Schaltplan VBus + Stromversorgung vbusesp_max_sch_2.png | Schaltplan ESP8266 und IO vbusesp_max_assy.png | Bestückungsplan </gallery> =BOM= Möglichkeiten schaffen Komplexität. Wie bei den anderen Plattformen lässt sich der Adapter in verschiedenen Varianten aufbauen, wobei ich (auch wenn es gerade bei dieser anbietet) noch immer empfehle, die Optoisolierte aufzubauen. ==Decoder== Neben Optoisoliert und Direkt gibt es noch die Variante ohne ESP - dank der Stiftleiste rechts oben auf der Leiterkarte lässt sich der VBus-Anteil komplett unabhängig vom ESP-Anteil verwenden. Mit Säge und Fingerspitzengefühl lässt sich die Größe auch noch ein gutes Stück reduzieren. Als ESP8266-Modul kann das ESP01 und ESP12(-F) verwendet werden. Getestet wurde bis jetzt nur das ESP12-F, wobei nichts gegen das 01 sprechen dürfte. <tabs> <tab name="Optoisoliert"> Empfohlene Bestückungsvariante. <gallery> vbusesp_optiso_sch_1.png | Variantenschaltplan VBus vbusesp_optiso_sch_2.png | Variantenschaltplan ESP8266 vbusesp_optiso_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R18, R19, R22 || 10k || R0805 || RND 0805 1 10K |- | 1 || R24 || 10k || R0805 || RND 0805 1 100 |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 3 || R20, R21, R25 || 1k || R0805 || RND 0805 1 1k |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Direkt"> <gallery> vbusesp_direct_sch_1.png | Variantenschaltplan VBus vbusesp_direct_sch_2.png | Variantenschaltplan ESP8266 vbusesp_direct_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R18, R19, R22 || 10k || R0805 || RND 0805 1 10K |- | 1 || R24 || 10k || R0805 || RND 0805 1 100 |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 3 || R20, R21, R25 || 1k || R0805 || RND 0805 1 1k |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 2 || Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Optoisoliert (ohne ESP)"> Wer keinen ESP8266 verwenden aber die Vorzüge der verbesserten Schaltung haben möchte, kann den ESP-Anteil vollständig weglassen. Hierfür wird auf dieser Leiterkarte keine Stromversorgung benötigt, da diese vom jeweilig verwendeten Interface (z. B. SBC, USB-UART-Wandler, ...) bezogen werden kann. <gallery> vbusesp_optisonoesp_sch_1.png | Variantenschaltplan VBus vbusesp_optisonoesp_sch_2.png | Variantenschaltplan Interface vbusesp_optisonoesp_assy.png | Bestückungsplan vbusesp_vbusonly_pinout.png | Anschlussbelegung des UART </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> ==Stromversorgung== Für die Stromversorgung gibt es ebenfalls zwei Möglichkeiten: Entweder mit LDO oder Schaltwandler. Wer auf Nummer sicher gehen will, nimmt die billigere LDO-Variante, da ich noch keine Gelegenheit hatte letztere zu testen. Die etwas höhere Stromaufnahme dürfte wahrscheinlich nicht allzu sehr ins Gewicht fallen. <tabs> <tab name="Linearregler"> Empfohlene Bestückungsvariante. <gallery> vbusesp_vregldo_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregldo_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || REG1117 || SOT223 || NCP 1117 ST33T3G |} </tab> <tab name="Schaltwandler"> <gallery> vbusesp_vregsmps_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregsmps_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C9 || 100n || C0603 || X7R-G0603 100N |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C12 || 10p || C0603 || NPO-G0603 10P |- | 1 || R17 || 15k || R0603 || RND 0603 1 15K |- | 1 || L1 || 15u || 242408FPS || L-242408FPS 15µ |- | 1 || R16 || 47k || R0603 || RND 0603 1 47K |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || D6 || BAT43WS || SOD323-W || BAT 43WS |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || IC2 || MCP16301 || SOT23-6 || MCP 16301T-I/CHY |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || D4 || SS13L || SUBSMA || SS 13L |} </tab> </tabs> =Inbetriebnahme/Benutzung= ==Flashing== Wird ein ESP8266 verwendet, muss natürlich erst einmal die Software auf den Mikrocontroller. Das Problem: Der Softwaredownload findet über den selben UART statt, der auch für das VBus-Interface statt. Nun könnte man mit Multiplexern arbeiten, was im Idealfall nur einmal benutzt werden würde und somit mit Kanonen auf Spatzen geschossen wäre. Aus den gleichen Grund gibt es keinen USB-UART-Konverter auf dem Board: Braucht nur Platz und kostet. Deshalb wird für das erstmalige Flashen ein USB-UART-Adapter, der RTS/DTR anbietet, benötigt. Dieser sollte idealerweise mit 3,3 V arbeite, wobei der ESP wohl auch 5 V toleriert. Die beiden Transistoren für Reset und Bootloader nach WittyCloud/NodeMCU sind bereits vorhanden. Die 5 V-Stromversorgung muss entweder über den USB-Port oder der Stiftleiste SV2 kommen, die Anschlussbelegung des UART an SV4 ist wie folgt: {| class="wikitable" ! Pin || Signal vom UART-Adapter |- | 1 || DTR |- | 3 || TX |- | 7 || RX |- | 9 || RTS |} <gallery> vbusesp_prog_1.png | Anschlussbelegung für das Programmieren per UART vbusesp_prog_2.jpg | Verwendung des WittyCloud-USB-Wandlers </gallery> Liegt das Trägerboard eines WittyCloud herum, müssen DTR und RTS gefädelt werden. ==Betrieb== Ist die Firmware auf dem Chip und es sollen Daten vom VBus decodiert werden, muss ein Jumper zwischen Pin 3 und 4 an SV4 oder ein Lötpunkt auf SJ1 gesetzt werden: <gallery> vbusesp_txjumper.png | UART-Verbindung zwischen VBus und ESP8266 </gallery> =Firmware= Zugegebenermaßen: ich habe zwar seit Jahren ein paar ESP8266-Module herumliegen, mich aber nie so richtig damit auseinandergesetzt. Aber das macht nichts: [https://tasmota.github.io/docs/ Tasmota] unterstützt verschiedene [https://tasmota.github.io/docs/Smart-Meter-Interface/ Smart Metering]-Anbindungen, für die die Firmware allerdings angepasst selbst kompiliert werden muss. Michael hat sich (mit der Unterstützung aus der Tasmota-Community) daran gemacht und freundlicherweise die nötigen Anpassungen zur Verfügung gestellt: Folgendes muss in der Datei <code>tasmota/user_config_override.h</code> ergänzt werden: <source lang="C"> #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ #ifndef USE_SCRIPT #define USE_SCRIPT #endif #ifndef USE_SML_M #define USE_SML_M #endif #ifdef USE_RULES #undef USE_RULES #endif #ifndef SML_REPLACE_VARS #define SML_REPLACE_VARS #endif #ifndef USE_SML_SCRIPT_CMD #define USE_SML_SCRIPT_CMD #endif #ifndef SML_MAX_VARS #define SML_MAX_VARS 20 #endif #ifndef USE_SCRIPT_JSON_EXPORT #define USE_SCRIPT_JSON_EXPORT #endif #ifndef USE_SCRIPT_WEB_DISPLAY #define USE_SCRIPT_WEB_DISPLAY #endif </source> ==Konfiguration== Nach dem Flashen des Mikrocontrollers, was für fertige Builds auch über den Tasmotizer erfolgen kann, kann unter <code>Main-Menu -> Console -> Edit Script</code> das [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus Script ergänzt] werden. Mit dem Befehl <code>sensor53 d1</code> kann man den Header für die [https://tasmota.github.io/docs/Smart-Meter-Interface/#meter-metrics Meter Metrics] ermitteln und im Script entsprechend anpassen. Für die RemaSol B/2 sieht das wie folgt aus: <source> r="1,aa10005d101000010a67" coltemp=0 Byte1=0 Byte2=0 >S coltemp=sml[1] Byte1=coltemp>>8 Byte2=coltemp&0xff if Byte1==0x00 { coltemp=coltemp&0xff } if Byte1==0xff { coltemp=(coltemp-0x10000) } coltemp=coltemp*0.1 >B =>sensor53 r >M 1 +1,3,v,0,9600,Solar %r%vo0uw@1,KollektorBase,°C,kolbase,2 %r%vo0uw@10,KollektorOrg,°C,kolorg,2 %r%vo2uw@10,Speicher unten,°C,spu,1 %r%vo4uw@10,Speicher oben,°C,spo,1 %r%vo8ub@1,Pumpe,%%,pump,0 # >J ,"Calculated":{"kol":%coltemp%} >W Kollektor berechnet: {m} %coltemp% °C </source> Anmerkung: Hierbei handelt es sich um einen direkten Copy & Paste aus Michaels Script. Je nach Konfiguration der Anlage kann es Abweichungen geben. Um den Fragen zuvorzukommen - die Anpassung auf die Jeweilige Anlage beginnt in der ersten Zeile: <code> r="1,<span class="hb1">aa</span><span class="hb2">1000</span><span class="hb3">5d10</span><span class="hb4">10</span><span class="hb5">0001</span><span class="hb6">0a</span><span class="hb7">67</span>" </code> Die Farben entsprechen dem Beispiel von der [[VBus-Decoder#Protokoll|Artikelhauptseite]], kurzum: * <span class="hb1">aa</span>: Sync-Wort * <span class="hb2">1000</span>: Zieladresse * <span class="hb3">5d10</span>: Quelladresse * <span class="hb4">10</span>: Protokollversion * <span class="hb5">0001</span>: Befehl * <span class="hb6">0a</span>: Anzahl Nutzdatenframes * <span class="hb7">67</span>: Prüfsumme Die <span class="hb3">Quelladresse</span> kann in der [https://danielwippermann.github.io/resol-vbus/#/vsf VBus-Spezifikation nachgeschlagen werden]. Zu beachten ist hier die Endianness: was in der Doku als <code>0x1234</code> geschrieben ist, muss hier als <code>3412</code> angegeben werden. Anschließend muss man auf der [https://danielwippermann.github.io/resol-vbus/#/vsf oben genannten Seite] nach dem Command 0x0100 für den entsprechenden Regler suchen. Dazu am besten oben nach 0x0100 filtern und dann mit Strg+F die Quelladresse finden. Klickt man in der Zeile auf <code>Bytes</code> bekommt man die Länge der Nachricht, wobei man 1 addieren muss, da es sich um Offsets handelt. Beim RemaSol 1/2 (bzw. DeDietrich Sol Plus ER 709) ist der größte Offset 39, also 40 Bytes. Mit dem Wissen, dass ein Frame 4 Byte enthält, ergibt sich eine Länge von 10 Frames, was einem Hexadezimalwert von <span class="hb6">0x0A</span> entspricht. Nun muss man nur noch die Prüfsumme berechnen (oder durch Schnüffeln am UART ermitteln) Für die Feldzuordnung lohnt sich ein scharfer Blick und Vergleich der <code>Fields</code>-Seite für die [https://danielwippermann.github.io/resol-vbus/#/vsf/fields/00_0010_4221_10_0100 DeltaSol BS Plus] und dem Beispiel in der [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus dieses Reglers] in der Tasmota-Doku. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. Achtung: Es handelt sich um Version 0.1, auf der sich 3 kleine Fehler befinden, die sich allerdings mit Fädeldraht korrigieren lassen. =Downloads= * [[Datei:Vbusesp_0.2.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:ESP8266]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 4a01c617e9eb6ad2bdf537d1f3c4dcdcabaeff61 1727 1726 2021-12-13T20:58:33Z Chris 2 /* Motivation */ typo wikitext text/x-wiki [[Bild:vbusesp_top.jpg|thumb|Aufgebauter Leiterkarte (v0.1)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Wenn Basteln und IoT aufeinandertreffen, kommt man fast nicht an den Mikrocontrollern von Espressif vorbei. Genau aus diesem Grund hatte ich schon länger die Idee, ein Leiterkärtchen mit dem ESP8266 zu machen. Also warum nicht einfach den beliebten VBus ohne großes Strippenziehen ins Netzwerk bringen? =Schaltung= Die Schaltung für den VBus basiert auf der für den [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Raspi (v1.3)]], aufseiten des ESP habe ich mich von den verschiedenen Bastelboards inspirieren lassen und die Möglichkeit vorgesehen, sowohl die kleinen ESP01- als auch die etwas vielseitigeren ESP12-Module einzusetzen. Die Versorgung findet über eine Stiftleiste (bzw. angelötete Drähte) oder über eine Micro-USB-Buchse statt. Diese dient nur der Stromversorgung - mehr zum Programmieren des ESP weiter unten. Bei der Verwendung des ESP12-Moduls stehen zusätzlich zum VBus-Interface noch die GPIOs 12, 13, 14 und 16 sowie der ADC-Eingang und die 3,3V-Versorgung zur Verfügung. Hier kann weitere Peripherie wie Sensoren oder Displays angeschlossen werden. Für den Aufbau gibt es mehrere Varianten, die unten aufgeführt sind. Diese können über die Tabs ausgewählt und müssen beim Besorgen der Bauteile und selbstverständlich beim Zusammenbau kombiniert werden. Die theoretische Maximalbestückung sieht wie folgt aus: <gallery> vbusesp_max_sch_1.png | Schaltplan VBus + Stromversorgung vbusesp_max_sch_2.png | Schaltplan ESP8266 und IO vbusesp_max_assy.png | Bestückungsplan </gallery> =BOM= Möglichkeiten schaffen Komplexität. Wie bei den anderen Plattformen lässt sich der Adapter in verschiedenen Varianten aufbauen, wobei ich (auch wenn es gerade bei dieser anbietet) noch immer empfehle, die Optoisolierte aufzubauen. ==Decoder== Neben Optoisoliert und Direkt gibt es noch die Variante ohne ESP - dank der Stiftleiste rechts oben auf der Leiterkarte lässt sich der VBus-Anteil komplett unabhängig vom ESP-Anteil verwenden. Mit Säge und Fingerspitzengefühl lässt sich die Größe auch noch ein gutes Stück reduzieren. Als ESP8266-Modul kann das ESP01 und ESP12(-F) verwendet werden. Getestet wurde bis jetzt nur das ESP12-F, wobei nichts gegen das 01 sprechen dürfte. <tabs> <tab name="Optoisoliert"> Empfohlene Bestückungsvariante. <gallery> vbusesp_optiso_sch_1.png | Variantenschaltplan VBus vbusesp_optiso_sch_2.png | Variantenschaltplan ESP8266 vbusesp_optiso_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R18, R19, R22 || 10k || R0805 || RND 0805 1 10K |- | 1 || R24 || 10k || R0805 || RND 0805 1 100 |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 3 || R20, R21, R25 || 1k || R0805 || RND 0805 1 1k |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Direkt"> <gallery> vbusesp_direct_sch_1.png | Variantenschaltplan VBus vbusesp_direct_sch_2.png | Variantenschaltplan ESP8266 vbusesp_direct_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R18, R19, R22 || 10k || R0805 || RND 0805 1 10K |- | 1 || R24 || 10k || R0805 || RND 0805 1 100 |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 3 || R20, R21, R25 || 1k || R0805 || RND 0805 1 1k |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 2 || Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Optoisoliert (ohne ESP)"> Wer keinen ESP8266 verwenden aber die Vorzüge der verbesserten Schaltung haben möchte, kann den ESP-Anteil vollständig weglassen. Hierfür wird auf dieser Leiterkarte keine Stromversorgung benötigt, da diese vom jeweilig verwendeten Interface (z. B. SBC, USB-UART-Wandler, ...) bezogen werden kann. <gallery> vbusesp_optisonoesp_sch_1.png | Variantenschaltplan VBus vbusesp_optisonoesp_sch_2.png | Variantenschaltplan Interface vbusesp_optisonoesp_assy.png | Bestückungsplan vbusesp_vbusonly_pinout.png | Anschlussbelegung des UART </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> ==Stromversorgung== Für die Stromversorgung gibt es ebenfalls zwei Möglichkeiten: Entweder mit LDO oder Schaltwandler. Wer auf Nummer sicher gehen will, nimmt die billigere LDO-Variante, da ich noch keine Gelegenheit hatte letztere zu testen. Die etwas höhere Stromaufnahme dürfte wahrscheinlich nicht allzu sehr ins Gewicht fallen. <tabs> <tab name="Linearregler"> Empfohlene Bestückungsvariante. <gallery> vbusesp_vregldo_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregldo_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || REG1117 || SOT223 || NCP 1117 ST33T3G |} </tab> <tab name="Schaltwandler"> <gallery> vbusesp_vregsmps_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregsmps_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C9 || 100n || C0603 || X7R-G0603 100N |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C12 || 10p || C0603 || NPO-G0603 10P |- | 1 || R17 || 15k || R0603 || RND 0603 1 15K |- | 1 || L1 || 15u || 242408FPS || L-242408FPS 15µ |- | 1 || R16 || 47k || R0603 || RND 0603 1 47K |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || D6 || BAT43WS || SOD323-W || BAT 43WS |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || IC2 || MCP16301 || SOT23-6 || MCP 16301T-I/CHY |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || D4 || SS13L || SUBSMA || SS 13L |} </tab> </tabs> =Inbetriebnahme/Benutzung= ==Flashing== Wird ein ESP8266 verwendet, muss natürlich erst einmal die Software auf den Mikrocontroller. Das Problem: Der Softwaredownload findet über den selben UART statt, der auch für das VBus-Interface statt. Nun könnte man mit Multiplexern arbeiten, was im Idealfall nur einmal benutzt werden würde und somit mit Kanonen auf Spatzen geschossen wäre. Aus den gleichen Grund gibt es keinen USB-UART-Konverter auf dem Board: Braucht nur Platz und kostet. Deshalb wird für das erstmalige Flashen ein USB-UART-Adapter, der RTS/DTR anbietet, benötigt. Dieser sollte idealerweise mit 3,3 V arbeite, wobei der ESP wohl auch 5 V toleriert. Die beiden Transistoren für Reset und Bootloader nach WittyCloud/NodeMCU sind bereits vorhanden. Die 5 V-Stromversorgung muss entweder über den USB-Port oder der Stiftleiste SV2 kommen, die Anschlussbelegung des UART an SV4 ist wie folgt: {| class="wikitable" ! Pin || Signal vom UART-Adapter |- | 1 || DTR |- | 3 || TX |- | 7 || RX |- | 9 || RTS |} <gallery> vbusesp_prog_1.png | Anschlussbelegung für das Programmieren per UART vbusesp_prog_2.jpg | Verwendung des WittyCloud-USB-Wandlers </gallery> Liegt das Trägerboard eines WittyCloud herum, müssen DTR und RTS gefädelt werden. ==Betrieb== Ist die Firmware auf dem Chip und es sollen Daten vom VBus decodiert werden, muss ein Jumper zwischen Pin 3 und 4 an SV4 oder ein Lötpunkt auf SJ1 gesetzt werden: <gallery> vbusesp_txjumper.png | UART-Verbindung zwischen VBus und ESP8266 </gallery> =Firmware= Zugegebenermaßen: ich habe zwar seit Jahren ein paar ESP8266-Module herumliegen, mich aber nie so richtig damit auseinandergesetzt. Aber das macht nichts: [https://tasmota.github.io/docs/ Tasmota] unterstützt verschiedene [https://tasmota.github.io/docs/Smart-Meter-Interface/ Smart Metering]-Anbindungen, für die die Firmware allerdings angepasst selbst kompiliert werden muss. Michael hat sich (mit der Unterstützung aus der Tasmota-Community) daran gemacht und freundlicherweise die nötigen Anpassungen zur Verfügung gestellt: Folgendes muss in der Datei <code>tasmota/user_config_override.h</code> ergänzt werden: <source lang="C"> #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ #ifndef USE_SCRIPT #define USE_SCRIPT #endif #ifndef USE_SML_M #define USE_SML_M #endif #ifdef USE_RULES #undef USE_RULES #endif #ifndef SML_REPLACE_VARS #define SML_REPLACE_VARS #endif #ifndef USE_SML_SCRIPT_CMD #define USE_SML_SCRIPT_CMD #endif #ifndef SML_MAX_VARS #define SML_MAX_VARS 20 #endif #ifndef USE_SCRIPT_JSON_EXPORT #define USE_SCRIPT_JSON_EXPORT #endif #ifndef USE_SCRIPT_WEB_DISPLAY #define USE_SCRIPT_WEB_DISPLAY #endif </source> ==Konfiguration== Nach dem Flashen des Mikrocontrollers, was für fertige Builds auch über den Tasmotizer erfolgen kann, kann unter <code>Main-Menu -> Console -> Edit Script</code> das [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus Script ergänzt] werden. Mit dem Befehl <code>sensor53 d1</code> kann man den Header für die [https://tasmota.github.io/docs/Smart-Meter-Interface/#meter-metrics Meter Metrics] ermitteln und im Script entsprechend anpassen. Für die RemaSol B/2 sieht das wie folgt aus: <source> r="1,aa10005d101000010a67" coltemp=0 Byte1=0 Byte2=0 >S coltemp=sml[1] Byte1=coltemp>>8 Byte2=coltemp&0xff if Byte1==0x00 { coltemp=coltemp&0xff } if Byte1==0xff { coltemp=(coltemp-0x10000) } coltemp=coltemp*0.1 >B =>sensor53 r >M 1 +1,3,v,0,9600,Solar %r%vo0uw@1,KollektorBase,°C,kolbase,2 %r%vo0uw@10,KollektorOrg,°C,kolorg,2 %r%vo2uw@10,Speicher unten,°C,spu,1 %r%vo4uw@10,Speicher oben,°C,spo,1 %r%vo8ub@1,Pumpe,%%,pump,0 # >J ,"Calculated":{"kol":%coltemp%} >W Kollektor berechnet: {m} %coltemp% °C </source> Anmerkung: Hierbei handelt es sich um einen direkten Copy & Paste aus Michaels Script. Je nach Konfiguration der Anlage kann es Abweichungen geben. Um den Fragen zuvorzukommen - die Anpassung auf die Jeweilige Anlage beginnt in der ersten Zeile: <code> r="1,<span class="hb1">aa</span><span class="hb2">1000</span><span class="hb3">5d10</span><span class="hb4">10</span><span class="hb5">0001</span><span class="hb6">0a</span><span class="hb7">67</span>" </code> Die Farben entsprechen dem Beispiel von der [[VBus-Decoder#Protokoll|Artikelhauptseite]], kurzum: * <span class="hb1">aa</span>: Sync-Wort * <span class="hb2">1000</span>: Zieladresse * <span class="hb3">5d10</span>: Quelladresse * <span class="hb4">10</span>: Protokollversion * <span class="hb5">0001</span>: Befehl * <span class="hb6">0a</span>: Anzahl Nutzdatenframes * <span class="hb7">67</span>: Prüfsumme Die <span class="hb3">Quelladresse</span> kann in der [https://danielwippermann.github.io/resol-vbus/#/vsf VBus-Spezifikation nachgeschlagen werden]. Zu beachten ist hier die Endianness: was in der Doku als <code>0x1234</code> geschrieben ist, muss hier als <code>3412</code> angegeben werden. Anschließend muss man auf der [https://danielwippermann.github.io/resol-vbus/#/vsf oben genannten Seite] nach dem Command 0x0100 für den entsprechenden Regler suchen. Dazu am besten oben nach 0x0100 filtern und dann mit Strg+F die Quelladresse finden. Klickt man in der Zeile auf <code>Bytes</code> bekommt man die Länge der Nachricht, wobei man 1 addieren muss, da es sich um Offsets handelt. Beim RemaSol 1/2 (bzw. DeDietrich Sol Plus ER 709) ist der größte Offset 39, also 40 Bytes. Mit dem Wissen, dass ein Frame 4 Byte enthält, ergibt sich eine Länge von 10 Frames, was einem Hexadezimalwert von <span class="hb6">0x0A</span> entspricht. Nun muss man nur noch die Prüfsumme berechnen (oder durch Schnüffeln am UART ermitteln) Für die Feldzuordnung lohnt sich ein scharfer Blick und Vergleich der <code>Fields</code>-Seite für die [https://danielwippermann.github.io/resol-vbus/#/vsf/fields/00_0010_4221_10_0100 DeltaSol BS Plus] und dem Beispiel in der [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus dieses Reglers] in der Tasmota-Doku. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. Achtung: Es handelt sich um Version 0.1, auf der sich 3 kleine Fehler befinden, die sich allerdings mit Fädeldraht korrigieren lassen. =Downloads= * [[Datei:Vbusesp_0.2.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:ESP8266]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 42e14efd615cfbb79359a4122023de0b31c7d4b1 1728 1727 2021-12-13T21:00:35Z Chris 2 /* Flashing */ typo wikitext text/x-wiki [[Bild:vbusesp_top.jpg|thumb|Aufgebauter Leiterkarte (v0.1)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Wenn Basteln und IoT aufeinandertreffen, kommt man fast nicht an den Mikrocontrollern von Espressif vorbei. Genau aus diesem Grund hatte ich schon länger die Idee, ein Leiterkärtchen mit dem ESP8266 zu machen. Also warum nicht einfach den beliebten VBus ohne großes Strippenziehen ins Netzwerk bringen? =Schaltung= Die Schaltung für den VBus basiert auf der für den [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Raspi (v1.3)]], aufseiten des ESP habe ich mich von den verschiedenen Bastelboards inspirieren lassen und die Möglichkeit vorgesehen, sowohl die kleinen ESP01- als auch die etwas vielseitigeren ESP12-Module einzusetzen. Die Versorgung findet über eine Stiftleiste (bzw. angelötete Drähte) oder über eine Micro-USB-Buchse statt. Diese dient nur der Stromversorgung - mehr zum Programmieren des ESP weiter unten. Bei der Verwendung des ESP12-Moduls stehen zusätzlich zum VBus-Interface noch die GPIOs 12, 13, 14 und 16 sowie der ADC-Eingang und die 3,3V-Versorgung zur Verfügung. Hier kann weitere Peripherie wie Sensoren oder Displays angeschlossen werden. Für den Aufbau gibt es mehrere Varianten, die unten aufgeführt sind. Diese können über die Tabs ausgewählt und müssen beim Besorgen der Bauteile und selbstverständlich beim Zusammenbau kombiniert werden. Die theoretische Maximalbestückung sieht wie folgt aus: <gallery> vbusesp_max_sch_1.png | Schaltplan VBus + Stromversorgung vbusesp_max_sch_2.png | Schaltplan ESP8266 und IO vbusesp_max_assy.png | Bestückungsplan </gallery> =BOM= Möglichkeiten schaffen Komplexität. Wie bei den anderen Plattformen lässt sich der Adapter in verschiedenen Varianten aufbauen, wobei ich (auch wenn es gerade bei dieser anbietet) noch immer empfehle, die Optoisolierte aufzubauen. ==Decoder== Neben Optoisoliert und Direkt gibt es noch die Variante ohne ESP - dank der Stiftleiste rechts oben auf der Leiterkarte lässt sich der VBus-Anteil komplett unabhängig vom ESP-Anteil verwenden. Mit Säge und Fingerspitzengefühl lässt sich die Größe auch noch ein gutes Stück reduzieren. Als ESP8266-Modul kann das ESP01 und ESP12(-F) verwendet werden. Getestet wurde bis jetzt nur das ESP12-F, wobei nichts gegen das 01 sprechen dürfte. <tabs> <tab name="Optoisoliert"> Empfohlene Bestückungsvariante. <gallery> vbusesp_optiso_sch_1.png | Variantenschaltplan VBus vbusesp_optiso_sch_2.png | Variantenschaltplan ESP8266 vbusesp_optiso_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R18, R19, R22 || 10k || R0805 || RND 0805 1 10K |- | 1 || R24 || 10k || R0805 || RND 0805 1 100 |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 3 || R20, R21, R25 || 1k || R0805 || RND 0805 1 1k |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Direkt"> <gallery> vbusesp_direct_sch_1.png | Variantenschaltplan VBus vbusesp_direct_sch_2.png | Variantenschaltplan ESP8266 vbusesp_direct_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R18, R19, R22 || 10k || R0805 || RND 0805 1 10K |- | 1 || R24 || 10k || R0805 || RND 0805 1 100 |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 3 || R20, R21, R25 || 1k || R0805 || RND 0805 1 1k |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 2 || Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Optoisoliert (ohne ESP)"> Wer keinen ESP8266 verwenden aber die Vorzüge der verbesserten Schaltung haben möchte, kann den ESP-Anteil vollständig weglassen. Hierfür wird auf dieser Leiterkarte keine Stromversorgung benötigt, da diese vom jeweilig verwendeten Interface (z. B. SBC, USB-UART-Wandler, ...) bezogen werden kann. <gallery> vbusesp_optisonoesp_sch_1.png | Variantenschaltplan VBus vbusesp_optisonoesp_sch_2.png | Variantenschaltplan Interface vbusesp_optisonoesp_assy.png | Bestückungsplan vbusesp_vbusonly_pinout.png | Anschlussbelegung des UART </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> ==Stromversorgung== Für die Stromversorgung gibt es ebenfalls zwei Möglichkeiten: Entweder mit LDO oder Schaltwandler. Wer auf Nummer sicher gehen will, nimmt die billigere LDO-Variante, da ich noch keine Gelegenheit hatte letztere zu testen. Die etwas höhere Stromaufnahme dürfte wahrscheinlich nicht allzu sehr ins Gewicht fallen. <tabs> <tab name="Linearregler"> Empfohlene Bestückungsvariante. <gallery> vbusesp_vregldo_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregldo_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || REG1117 || SOT223 || NCP 1117 ST33T3G |} </tab> <tab name="Schaltwandler"> <gallery> vbusesp_vregsmps_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregsmps_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C9 || 100n || C0603 || X7R-G0603 100N |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C12 || 10p || C0603 || NPO-G0603 10P |- | 1 || R17 || 15k || R0603 || RND 0603 1 15K |- | 1 || L1 || 15u || 242408FPS || L-242408FPS 15µ |- | 1 || R16 || 47k || R0603 || RND 0603 1 47K |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || D6 || BAT43WS || SOD323-W || BAT 43WS |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || IC2 || MCP16301 || SOT23-6 || MCP 16301T-I/CHY |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || D4 || SS13L || SUBSMA || SS 13L |} </tab> </tabs> =Inbetriebnahme/Benutzung= ==Flashing== Wird ein ESP8266 verwendet, muss natürlich erst einmal die Software auf den Mikrocontroller. Das Problem: Der Softwaredownload findet über den selben UART statt, der auch für das VBus-Interface statt. Nun könnte man mit Multiplexern arbeiten, was im Idealfall nur einmal benutzt werden würde und somit mit Kanonen auf Spatzen geschossen wäre. Aus dem gleichen Grund gibt es keinen USB-UART-Konverter auf dem Board: Braucht nur Platz und kostet. Deshalb wird für das erstmalige Flashen ein USB-UART-Adapter, der RTS/DTR anbietet, benötigt. Dieser sollte idealerweise mit 3,3 V arbeite, wobei der ESP wohl auch 5 V toleriert. Die beiden Transistoren für Reset und Bootloader nach WittyCloud/NodeMCU sind bereits vorhanden. Die 5 V-Stromversorgung muss entweder über den USB-Port oder der Stiftleiste SV2 kommen, die Anschlussbelegung des UART an SV4 ist wie folgt: {| class="wikitable" ! Pin || Signal vom UART-Adapter |- | 1 || DTR |- | 3 || TX |- | 7 || RX |- | 9 || RTS |} <gallery> vbusesp_prog_1.png | Anschlussbelegung für das Programmieren per UART vbusesp_prog_2.jpg | Verwendung des WittyCloud-USB-Wandlers </gallery> Liegt das Trägerboard eines WittyCloud herum, müssen DTR und RTS gefädelt werden. ==Betrieb== Ist die Firmware auf dem Chip und es sollen Daten vom VBus decodiert werden, muss ein Jumper zwischen Pin 3 und 4 an SV4 oder ein Lötpunkt auf SJ1 gesetzt werden: <gallery> vbusesp_txjumper.png | UART-Verbindung zwischen VBus und ESP8266 </gallery> =Firmware= Zugegebenermaßen: ich habe zwar seit Jahren ein paar ESP8266-Module herumliegen, mich aber nie so richtig damit auseinandergesetzt. Aber das macht nichts: [https://tasmota.github.io/docs/ Tasmota] unterstützt verschiedene [https://tasmota.github.io/docs/Smart-Meter-Interface/ Smart Metering]-Anbindungen, für die die Firmware allerdings angepasst selbst kompiliert werden muss. Michael hat sich (mit der Unterstützung aus der Tasmota-Community) daran gemacht und freundlicherweise die nötigen Anpassungen zur Verfügung gestellt: Folgendes muss in der Datei <code>tasmota/user_config_override.h</code> ergänzt werden: <source lang="C"> #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ #ifndef USE_SCRIPT #define USE_SCRIPT #endif #ifndef USE_SML_M #define USE_SML_M #endif #ifdef USE_RULES #undef USE_RULES #endif #ifndef SML_REPLACE_VARS #define SML_REPLACE_VARS #endif #ifndef USE_SML_SCRIPT_CMD #define USE_SML_SCRIPT_CMD #endif #ifndef SML_MAX_VARS #define SML_MAX_VARS 20 #endif #ifndef USE_SCRIPT_JSON_EXPORT #define USE_SCRIPT_JSON_EXPORT #endif #ifndef USE_SCRIPT_WEB_DISPLAY #define USE_SCRIPT_WEB_DISPLAY #endif </source> ==Konfiguration== Nach dem Flashen des Mikrocontrollers, was für fertige Builds auch über den Tasmotizer erfolgen kann, kann unter <code>Main-Menu -> Console -> Edit Script</code> das [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus Script ergänzt] werden. Mit dem Befehl <code>sensor53 d1</code> kann man den Header für die [https://tasmota.github.io/docs/Smart-Meter-Interface/#meter-metrics Meter Metrics] ermitteln und im Script entsprechend anpassen. Für die RemaSol B/2 sieht das wie folgt aus: <source> r="1,aa10005d101000010a67" coltemp=0 Byte1=0 Byte2=0 >S coltemp=sml[1] Byte1=coltemp>>8 Byte2=coltemp&0xff if Byte1==0x00 { coltemp=coltemp&0xff } if Byte1==0xff { coltemp=(coltemp-0x10000) } coltemp=coltemp*0.1 >B =>sensor53 r >M 1 +1,3,v,0,9600,Solar %r%vo0uw@1,KollektorBase,°C,kolbase,2 %r%vo0uw@10,KollektorOrg,°C,kolorg,2 %r%vo2uw@10,Speicher unten,°C,spu,1 %r%vo4uw@10,Speicher oben,°C,spo,1 %r%vo8ub@1,Pumpe,%%,pump,0 # >J ,"Calculated":{"kol":%coltemp%} >W Kollektor berechnet: {m} %coltemp% °C </source> Anmerkung: Hierbei handelt es sich um einen direkten Copy & Paste aus Michaels Script. Je nach Konfiguration der Anlage kann es Abweichungen geben. Um den Fragen zuvorzukommen - die Anpassung auf die Jeweilige Anlage beginnt in der ersten Zeile: <code> r="1,<span class="hb1">aa</span><span class="hb2">1000</span><span class="hb3">5d10</span><span class="hb4">10</span><span class="hb5">0001</span><span class="hb6">0a</span><span class="hb7">67</span>" </code> Die Farben entsprechen dem Beispiel von der [[VBus-Decoder#Protokoll|Artikelhauptseite]], kurzum: * <span class="hb1">aa</span>: Sync-Wort * <span class="hb2">1000</span>: Zieladresse * <span class="hb3">5d10</span>: Quelladresse * <span class="hb4">10</span>: Protokollversion * <span class="hb5">0001</span>: Befehl * <span class="hb6">0a</span>: Anzahl Nutzdatenframes * <span class="hb7">67</span>: Prüfsumme Die <span class="hb3">Quelladresse</span> kann in der [https://danielwippermann.github.io/resol-vbus/#/vsf VBus-Spezifikation nachgeschlagen werden]. Zu beachten ist hier die Endianness: was in der Doku als <code>0x1234</code> geschrieben ist, muss hier als <code>3412</code> angegeben werden. Anschließend muss man auf der [https://danielwippermann.github.io/resol-vbus/#/vsf oben genannten Seite] nach dem Command 0x0100 für den entsprechenden Regler suchen. Dazu am besten oben nach 0x0100 filtern und dann mit Strg+F die Quelladresse finden. Klickt man in der Zeile auf <code>Bytes</code> bekommt man die Länge der Nachricht, wobei man 1 addieren muss, da es sich um Offsets handelt. Beim RemaSol 1/2 (bzw. DeDietrich Sol Plus ER 709) ist der größte Offset 39, also 40 Bytes. Mit dem Wissen, dass ein Frame 4 Byte enthält, ergibt sich eine Länge von 10 Frames, was einem Hexadezimalwert von <span class="hb6">0x0A</span> entspricht. Nun muss man nur noch die Prüfsumme berechnen (oder durch Schnüffeln am UART ermitteln) Für die Feldzuordnung lohnt sich ein scharfer Blick und Vergleich der <code>Fields</code>-Seite für die [https://danielwippermann.github.io/resol-vbus/#/vsf/fields/00_0010_4221_10_0100 DeltaSol BS Plus] und dem Beispiel in der [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus dieses Reglers] in der Tasmota-Doku. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. Achtung: Es handelt sich um Version 0.1, auf der sich 3 kleine Fehler befinden, die sich allerdings mit Fädeldraht korrigieren lassen. =Downloads= * [[Datei:Vbusesp_0.2.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:ESP8266]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 2838c5039ef0260ad79a578b2393f61a0e8adc66 Datei:Feuer powercon.jpg 6 758 1729 2021-12-23T14:30:29Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Feuer USB.jpg 6 759 1730 2021-12-23T14:30:29Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Feuer assy.jpg 6 760 1731 2021-12-23T14:30:29Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Feuer bot.jpg 6 761 1732 2021-12-23T14:30:29Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Feuer top.jpg 6 762 1733 2021-12-23T14:30:29Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Feuer alte Leitung.jpg 6 763 1734 2021-12-23T14:30:29Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Feuer installiert.jpg 6 764 1735 2021-12-23T14:30:30Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Feuer Stall beleuchtet.jpg 6 765 1736 2021-12-23T14:30:30Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Feuer top on.jpg 6 766 1737 2021-12-23T14:31:14Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 LED-Lagerfeuer 0 767 1738 2021-12-23T14:32:33Z Chris 2 Seite erstellt wikitext text/x-wiki Mein Vater stellt in der lokalen Dorfkirche jedes Jahr zu Weihnachten die Krippe auf. Diese wurde um 1920 gebaut und vermutlich stammt ein Teil der verbauten Beleuchtung noch von damals. Durch das Alter und dem Übersommern in einer einfachen freistehenden Garage ist die Installation mittlerweile etwas morsch: <gallery> Feuer_alte_Leitung.jpg | Alte Leitung </gallery> Aus diesem Grund sollte der Aufbau ein bisschen auf Vordermann gebracht werden. =Ausgangssituation= Auf der Haben-Seite steht die Krippe mit 60 Watt Glühobst im Stall und einer vermutlich 5 Watt-Funzel im Hirtenfeuer, die diesem mit einem Pergamentpapier ein rotes Ambiente verpasst. Beim Soll gibt es hauptsächlich den Punkt "soll nicht abbrennen", zumal sehr viel trockenes Moos und brennbares Material werwendet ist. =Lösung= Aufgrund der niedrigen Spannung und der breiten Verfügbarkeit wird die Versorgung auf USB umgestellt. ==Stallbeleuchtung== Im Lager liegt noch ein 10 cm langes COB-LED-Modul herum, das schon seinen Platz auf einem Kühlkörper gefunden hat. Da es mit 12 V versorgt werden muss, kommt noch ein [Reparatur_R&S_CMU200_Hintergrundbeleuchtung#LED-Treiber|Boost-Konverter] davor - mit dem netten Nebeneffekt, dass man die Helligkeit je nach Bedarf einstellen kann. ==Hirtenfeuer== Auch hier könnte es im einfachsten Fall ein direkter Ersatz mit einer weißen LED sein - aber das wäre langweilig. ===Hardware=== Stattdessen sind auf einer Punktraster-Leiterkarte 22 SMD-LEDs gelandet, 6 davon orange, der Rest rot. Alle LEDs sind in Strängen von zwei angeordnet, wobei ein paar Stränge parallel geschaltet sind - aus dem einfachen Grund, dass ich nicht mehr als 8 Kanäle implementieren wollte. Mit jeweils 2 LEDs in Reihe und einem Strom von etwa 7,5 mA kamen jeweils Widerstände mit 160 Ohm in Reihe. Auf der anderen Seite der Leiterkarte sitzt ein ATtiny44A und eine Bank an BSS138. Zwar hätte der Mikrocontroller die Ketten direkt treiben können, allerdings ist der Strom in Summe über dem, den er abkann. Zusätzlich finden noch Abblockkondensatoren und eine ESD-Diode. Einen Schaltplan aufgrund der Einfachheit gibt es nicht, alle LEDs (bzw. die zugehörigen Transistoren) sind an PORTA angeschlossen. <gallery> Feuer_top.jpg | LED-Seite Feuer_bot.jpg | Mikrocontroller und Peripherie Feuer_top_on.jpg | Beleuchtung aktiv </gallery> ===Firmware=== {{Infobox AVR | Typ = ATTiny44A | Takt = 8 | FuseH = DF | FuseL = E2 | FuseE = FF }} Wie programmiert man ein Feuer, das eher ruhig glimmt anstatt lodernde Flamen zu speien? Mein erster Ansatz war: Zufall. Die Helligkeiten werden in einem festen Zeitraster mit einem zufälligen Wert beschrieben. Nicht so richtig schlecht, aber eben auch nicht so richtig gut. Da die Firmware eh ein Aufguss von [[Anykey x6]] ist, kommt die Fading-"Engine" dazu, für die die Dauer ebenfalls zufällig gewählt wird. Die <code>main</code>-Funktion sieht dann wie folgt aus: <source lang="c"> int main(void) { wdt_enable(WDTO_1S); leddrv_init(); fader_init(); uint16_t postscale = 0; //pwm: ca. 469 Hz while (1) { bool update = leddrv_poll(); if(update == true) { postscale++; if(postscale == 1000) { //ca. 69 Hz. (nice) fader_tick(); postscale = 0; for(uint8_t i = 0; i < 8; i++) { if(fader_running(i) == false) { wdt_reset(); uint8_t d = rand() & 0x4F; uint8_t b = rand(); fader_set(i, b, d); } } wdt_reset(); } } } } </source> Die Zeiten in den Kommentaren sind eher Richtwerte, da der interne Oszillator nicht unbedingt genau ist. ===Ergebnis=== Das Ergebnis kann sich durchaus sehen lassen. Als Beispiel habe ich einfach mal zwei Clips aufgenommen: * [https://youtu.be/99Q9R-xaIWI direkter Blick, defokussiert] * [https://youtu.be/8LfEn3cYuh0 durch ein Taschentuch] In den Videos kann man den Unterschied zwischen roten und orangenen LEDs kaum unterscheiden, was auch - aber nicht nur - an der [[wpde:Farbunterabtastung|Farbunterabtastung]] der Aufnahme liegt. Der andere Grund: Die beiden Farben liegen bei den verwendeten Farben recht nah beieinander. Im Nachhinein hätte ich wohl eher einen Mix von 50:50 verwenden sollen. Eingebaut in das Lagerfeuer und ein bisschen Füllwatte für Kissen sieht das Lagerfeuer nun wie folgt aus: <gallery> Feuer_assy.jpg | Vorbereitetes Lagerfeuer </gallery> ==Sternenhimmel== Eher in einem Nebensatz erwähnte mein Vater (vielleicht auch da es eine andere Krippe in Familienbesitz hat), ob nicht ein Sternenhimmel ganz schön wäre. Nach dem obligatorisch-schwäbischen "wozu denn, gab's bis jetzt doch auch nicht", ging der Klick doch auf eBay. Das Lieferversprechen wurde gehalten und so konnte ich zwei Tage später (und einen Tag vor dem Aufbau) eine Drahtlichterkette mit 100 LEDs in den Händen halten. Mit einem auf ca. 10 mA eingestellten [[Mini-LED-Treiber]] sind die Leuchtdioden so hell, dass sie auch bei Umgebungslicht noch gut zu erkennen sind, aber die Umgebung nicht ausleuchten. Immer wieder erstaunlich, wie viel Licht bei nur 100 µA pro LED rauskommt. =Alles zusammen= Draußen ist kalt, bei der Hütte in der die Krippe steht gibt es keinen Strom (damit man den Lötkolben auspacken könnte) und gleichzeitig möchte ich nicht unnötig lange in der Kirche herumstehen - nicht nur, weil es die Arbeit der anderen verzögert. Deshalb soll alles "ready to use" sein. An den Enden der Stallbeleuchtung ist jeweils großzügig Schrumpfschlauch aufgezogen, gleiches beim Booster desselben - die "Schlapse" machen Bekanntschaft mit der Lochzange. Zack feddich: Montagelöcher. Am Booster ist zudem der Schraubenkopf des Poti freigeschnitten, damit die Helligkeit einfach eingestellt werden kann. Für das Lagerfeuer gibt es ca. 50 cm Leitung und den Versuch mit Dupont-Steckern einen Verpolschutz einzubauen. Im Nachhinein wäre vermutlich cleverer gewesen, Masse auf einen Stift und Versorgung auf die Buchse auf der einen Seite und entsprechend andersrum auf die andere Seite zu legen, aber mit angucken sollte auch das zu Schaffen sein. Den gleichen Konnektor gibt es für die Sterne. Da ich mehr generische 5 V- als USB-Netzteile herumliegen habe und sowieso eine USB-Verlängerung aufschneiden muss, wird der Hohlstecker geopfert und das weibliche Ende der Verlängerung angelötet. Um einem Herausrutschen und Ratlosigkeit entgegenzuwirken, lassen sich die USB-Stecker mit aufgeklebtem Klettband miteinander befestigen. Um den Fummelfaktor zu verringern, ist auf dem "oberen" Teil zusätzlich ein Stück Kabelbinder aufgeklebt. <gallery> Feuer_USB.jpg | USB-Stecker mit Klett-Verriegelung Feuer_powercon.jpg | "interne" Stromstecker der Krippe Feuer_Stall_beleuchtet.jpg | Beleuchteter Stall Feuer_installiert.jpg | Platzierte Feuerstelle </gallery> Wenn ich mal die Gelegenheit habe, kommen noch ein paar Fotos des vollen Assembles. =Download= * [[Datei:Lagerfeuer.zip]] Microchip Studio Projekt des Lagerfeuers [[Kategorie:AVR]] [[Kategorie:Modellbau]] [[Kategorie:Beleuchtung]] 5fe28b246ce5554fb674fd3f44e8bf7d15974b78 Datei:Lagerfeuer.zip 6 768 1739 2021-12-23T14:33:55Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Hauptseite 0 1 1740 1725 2021-12-23T14:34:50Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *23.12.2021 Es wird heimelig zu Weihnachten: ein [[LED-Lagerfeuer]] *13.12.2021 Mal wieder ein VBus-Decoder - jetzt für den [[VBus-Decoder/Adapter_für_den_ESP8266|ESP8266]] *07.09.2021 Eine aktualisierte Untersuchung des [[ECL-Bus-Protokoll]]s *12.07.2021 Der Pythoncode der [[MCP-USB-Bridge]] ist auf GitHub umgezogen und spricht nun mit dem MCP2210 (SPI) *26.02.2021 Und noch ein Update für den VBus-Decoder: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]] und [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]], sowie einem einfachen [[VBus-Decoder#Protokoll-Analysator|Protokoll-Analysator]] *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> d4412fe8e9c87c5ae0291cb12e7301d7183fecbc Briefkasteninnenbeleuchtung 0 445 1741 1549 2021-12-23T14:37:09Z Chris 2 wikitext text/x-wiki Zugegeben, es hört sich nicht nur bescheuert an, es ist auch so. Trotzdem hatte ich das Bedürfnis, eine Briefkasteninnenbeleuchtung zu bauen. Warum? Nein, nicht (nur) weil ich es kann, sondern weil sie durchaus praktisch ist = Problemstellung = Die Briefkästen des Mietshauses hier sind freistehend und in der dunklen Jahreszeit sieht man aufgrund der etwas ungünstig installierten Außenbeleuchtung durch den Einwurf nicht, ob Post gekommen ist. Durch das Öffnen der Frontklappe sieht und bekommt man zwar den Inhalt, aber dazu bin ich bei der geringen Anzahl von eintrudelnden Briefen schlicht zu faul. Umbauten müssen rückstandsfrei zu entfernen sein, schließlich will ichs nicht mit meinen Vermietern verscherzen. = Idee = In den Briefkasten soll mindestens eine LED, die durch das Öffnen des Deckels aktiviert wird. Die Befestigung findet über Magnete statt, die Stromversorgung durch Batterien. Damit diese nicht unnötig leergesaugt werden, soll die Beleuchtung zeitlich begrenzt sein. = Umsetzung = Zumindest bei der LED ist die Sache schnell klar: weiße PLCC2 liegen hier mehr als genug herum. Um sie sinnvoll zu betreiben, kommen 3 Mignon-Batterien in Serie zum Einsatz. Bei 3,3 Volt (also wenn die Zellen schon halb-platt sind) sind 7 mA mehr als genug, der passende Widerstand hierfür wäre 171 Ohm. Wäre, weil ein einfacher Vorwiderstand an dieser Stelle dumm ist - die Batteriespannung wird mit dem Ladestand fallen - und damit der Strom durch die LED. == LED-Treiber == Besser ist es deshalb, eine Konstantstromquelle zu verwenden. Die lässt sich sehr einfach aufbauen, zwei Transistoren und zwei Widerstände reichen. Der Strom wird über den unteren Widerstand und Transistor definiert: letzterer wird leitend, wenn seine Basis-Emitter-Spannung über ca. 0,7 Volt steigt - diese Spannung muss beim gewünschten Strom eingeprägt werden. Für den Widerstand gilt also: :<math>\textrm{R}=\frac{0.7}{\textrm{I}_\textrm{out}}</math> Der obere Transistor steuert den Strom durch die LED. Der Widerstand dient lediglich als Pull-up und ist daher eher unkritisch. Wer ihn hinreichend groß Dimensionierung will, muss sich den LED-Strom und den Verstärkungsfaktor ansehen. Die mechanische Integration ist einfach: ich habe noch kleine Leiterkärtchen, eigentlich für einen anderen Zweck, aber es passt alles für diese Schaltung drauf. Schrumpfschlauch drüber, kleine Magnete ran, nochmal Schrumpfschlauch. <gallery> Datei:Einfacher_LED-Treiber.png|Schaltplan des einfachen LED-Treibers Datei:Briefkasten_led.jpg|Aufgebauter LED-Triber mit LED, Magnet und Schrumpfschlauch </gallery> Bilder der Innereien gibt es leider keine. == Schalter == Für die Erkennung ob der Deckel offen ist gibt es viele Möglichkeiten: mechanischer Taster, Näherungssensoren, Neigungsschalter, Hallswitches, etc.. Mechanische Schalter brauchen in aller Regel viel Kraft (und viel Gegenkraft, die kann ich bei der Montage nicht bieten) und sind oft empfindlich gegen Feuchtigkeit. Viele Näherungssensoren (optisch, kapazitiv und induktiv) sind aktiv und haben einen relativ großen Eigenverbrauch. Nichts für langen Batteriebetrieb. Neigungsschalter geht, war aber früher dank Quecksilber eine ziemliche Sauerei; die aktuellen sind wahrscheinlich besser aber ich habe aufgrund des Temperaturbereichs Vorbehalte. Schlussendlich habe ich einen Reed-Kontakt verwendet. Hermetisch abgeschlossen, kraftfrei und kein Ruhestrom. Wenn man mechanisch faul ist oder nicht genug Grips in der Birne hat, braucht man einen Öffner - genau das (bzw. einen Wechsler) habe ich bestellt. Um die Integration vorweg zu nehmen: der Kontakt ist auf einer kleinen länglichen Leiterkarte gelandet - lang genug, um einen Magnet zur Montage am Briefkasten verwenden zu können. Jetzt kommt auch die Sache mit dem Grips: Der "Montagemagnet" war stark genug, damit das durch das Metall des Briefkastens verlaufende Feld den Kontakt öffnete. Mit geschickter Positionierung beider Magnete (der zur Montage und dem im Deckel) hätte ich die Felder so ausrichten können, dass sie sich im Deckel-zu-Fall neutralisiert hätten. Hätte-hätte... Aber auch so funktioniert es. Um vor Feuchtigkeit besser geschützt zu sein, kommt alles in Schrumpfschlauch und wird natürlich auf der etwas besser geschützten Seite des Briefkastens installiert. <gallery> Datei:Briefkasten_sensor.jpg|unten: Reedschalter auf Leiterkarte mit Magnet, oben (überbelichtet): Magnet </gallery> == Abschaltautomatik == {{Infobox AVR | Typ = ATtiny13 | Takt = 0,6 | FuseH = FF | FuseL = 61 }} Eigentlich wäre diese prädestiniert für eine Analogschaltung oder einen NE555. Schlussendlich wurde es aber ein ATtiny13. Der ist mit der Aufgabe zwar gänzlich unterfordert, braucht dafür im Schlaf nahezu keinen Strom und zudem fast keine Außenbeschaltung Das Programm könnte sehr einfach sein: Port initialisieren, Pin an, warten, Pin aus. Mit 4,8 MHz Takt braucht der Controller einige Milliampere, was in beiderlei Hinsicht unnötig viel ist. Über die CLKDIV-Fuse kann der Takt auf ein Achtel reduziert werden - besser aber trotzdem nicht überragend. Was ich beim Programmieren übersehen habe: den Watchdog als Taktquelle - 128 kHz und noch etwas stromsparender. Im [http://www.atmel.com/images/doc2535.pdf Datenblatt] kann man sich dazu Figure 19-1 und 19-5 anschauen. Demnach braucht der Chip bei 600 kHz (bei externer Taktquelle) zwischen 0,3 und 0,5 mA - mit dem Watchdog wären es lediglich 0,06 bis 0,09 mA. Statt warten per Delay kann man auch den internen Timer verwenden und die CPU bei Overflow wecken. Nur leider kann man mit weiterlaufendem Takt den Tiny nicht tief genug schlafen schicken, damit es richtig gut wird. Geht man in den Tiefschlaf, bleibt der Takt komplett weg und das war dann für den Timer. Glücklicherweise kann man den Watchdog so konfigurieren, dass er keinen Reset sondern einen Interrupt auslöst. Da er einen eigenen Oszillator hat, ist er zudem unabhängig vom Systemtakt. Sein Vorteiler lässt sich bis in den angenehmen Sekundenbereich einstellen. Im Power-Down und aktivem Watchdog braucht der Prozessor (Figure 19-14) zwischen 4,5 und 7,0 µA. Nachdem das Programm durch ist und sich der Bursche schlafen legt, sinkt der Stromverbrauch (Figure 19-13) auf sehr niedrige 0,2 bis 1,2 µA. Wo liegt nochmal die Selbstentladung von Alkali-Zellen? == Batteriewächter == Darf's ein bisschen mehr sein? Der ATtiny13 hat einen ADC, warum also nicht noch zusätzlich eine Warnung für bald leere Batterien einbauen? Einige AVRs können den ADC verkehrte Welt spielen lassen: Man kann die interne Referenz als Eingang wählen und die Versorgungsspannung als Referenz. Dadurch wird das Ergebnis zwar reziprok aber die Messung braucht keine externe Beschaltung und ist zudem sehr stromsparend. Geht hier leider nicht (Figure 14-1). Es muss also ein externer Spannungsteiler her. Der braucht permanent einen gewissen Strom und das ist Mist. Man kann die Widerstände zwar nach oben dimensionieren, dann wird die Messung durch ADC-bedingte Verfälschungen ungenauer. Ich bin einen etwas faulen (im Sinne von: warum mehr Zeit verschwenden) Kompromiss eingegangen: Der Spannungsteiler wird vom Schaltsignal für die LEDs versorgt. Dadurch haut der Strom nur für die maximal 30 Sekunden ab und zugleich hat der FET einen Pull-down am Gate, falls der IO doch mal floatet. Der Pad-Treiber im AVR dürfte einen leichten Spannungsabfall haben, aber zum einen kann man kalibrieren und zum anderen wird keine besonders hohe Genauigkeit benötigt. Bei der Dimensionierung muss man - wie bereits erwähnt - darauf achten, dass die Messung halbwegs sauber funktioniert aber gleichzeitig nicht unnötig viel Strom verbraucht wird. Natürlich muss auch der Teiler passen. Für diesen Zweck verwende ich gerne [https://www.muellerzumhagen.de/widerstand-ist-zwecklos-pointless-resistance/ Widerstand ist zwecklos], das die Paarung 33 kOhm (top) und 10 kOhm (bottom) ausspuckte. Damit ergibt sich eine maximal messbare Spannung von 4,73 V und ein Stromverbrauch von nicht ganz 105 µA bei 4,5 V. Die Auflösung wäre damit nicht ganz 4,6 mV - deutlich mehr als genug. Der ADC-Wert berechnet sich theoretisch wie folgt: :<math>\textrm{ADC}= \textrm{U}_{\textrm{bat}} \cdot \frac{10\textrm{ k}\Omega}{10\textrm{ k}\Omega+33\textrm{ k}\Omega} \cdot \frac{1024}{1.1\textrm{ V}}</math> Die Messung selbst ist geradeaus: Auswählen der Referenz und Eingang (PB4), Takt festlegen, Interrupt an und los geht's. Um etwas sinnvolles zu machen während die Messung durchgeführt wird, legt sich der Kern schlafen und wird wieder geweckt, sobald diese durch ist (sei(); nicht vergessen!). Anschließend wird der ADC-Wert ausgelesen und der Hardware-Block wieder deaktiviert. Um etwas bessere Ergebnisse zu erlangen, wird die Batteriespannung nicht direkt nach dem Start sondern nach einer Sekunde durchgeführt. Dadurch lassen sich zwei Dinge verknüpfen: Die Batterien sehen eine Last und man ist am richtigen Zeitpunkt, um die LEDs kurz auszuschalten - sollte die Batterieapannung das gesetzte Limit unterschritten haben. <gallery> Datei:Briefkasten_sch1.png|Schaltung </gallery> === Kalibrierung === Aufgrund der Beschaltung sah ich mich genötigt, den ADC zu testen. Der einfachste Weg dafür wäre UART, den es aber nicht gibt. Zumindest nicht in Hardware. Das Format ist relativ einfach, siehe [[wpde:Universal_Asynchronous_Receiver_Transmitter|Wikipedia]]. Idle high, Startbit, Daten und ein bisschen Pause fürs Stopbit (die ich mir gespart hab). Mit dem Wissen, wie lange ein NOP in der CPU dauert die Timings angepasst und los geht's. Mit "normalen" USB<>UART-Adaptern hat man allerdings wenig Spaß: meine Implementierung verwendet - der Faulheit wegen - 10 Datenbits und eine ziemlich krumme Baudrate, die halt einfach gerade gepasst hat. Der Logic Analyzer kann das, die meisten Wandler aber nicht. Aber wer will schon Interoperabilität? Das Ende vom Lied: die Berechnung von oben ist hinreichend genau. == Einbau == Dank der Magnete (Sensor + LEDs) und der Gravitation (Akkus und Mikrocontroller) lässt sich alles befestigen, wo es hin soll. Die Feinausrichtung des Reed-Kontakts geht schnell und einfach. = Es geht besser = Kein Projekt würde mal zweimal genau gleich machen. So auch hier. * LED-Treiber mit FET statt Bipolar-Transistoren aufbauen und dann auch gleich den gemeinsamen FET zum Schalten der Treiber sparen, indem die Versorgung von den Transistoren direkt vom Mikrocontroller kommt. * Spannungsteiler eine Nummer größer dimensionieren und etwas mehr Ungenauigkeit (who cares?!) in Kauf nehmen. Genauso würde ich im AVR gleich den Watchdog als Taktquelle nehmen. * Als Reed-Kontakt einen Schließer nehmen, ihn durch den Befestigungsmagnet "vorspannen" und das Feld durch den Magnet im Deckel neutralisieren. Geht sicher auch auf länger gut und senkt die Bauteilkosten. * Verringern der Betriebsdauer auf 10 Sekunden. Wer starrt schon 30 Sekunden in einen Briefkastenschlitz? <gallery> Datei:Briefkasten_sch2.png|Der etwas verbesserte Schaltplan </gallery> = Unterm Strich = Es ist wirklich sehr praktisch! Die Bilder unten wurden mit gleicher Belichtungseinstellung (mit eingeschalteter Außenbeleuchtung) aufgenommen und spiegeln in etwa die menschliche Helligkeitswahrnehmung wider: <gallery> Datei:Briefkasten_geschlossen.jpg|Geschlossen Datei:Briefkasten_offen.jpg|Geöffnet Datei:Briefkasten_oben.jpg|Blick von oben (keine Post) </gallery> = Trivia = * Der Freund meiner Nachbarin hält mich jetzt wohl für wahnsinnig, weil ich minutenlang vor dem Briefkasten stand und ihn öffnete und schloss ohne ihn zu bemerken. Warum schleicht er auch so herum? * Durch die Mechanische Verkopplung kann man das Klicken des Reedkontakts tatsächlich hören. * Auch nach gut 3 Jahren (12/2016 - 4/2020) funktioniert die Beleuchtung noch tadellos = Download = [[Datei:Briefkasten.zip|Schaltplan & Firmware]] [[Kategorie:AVR]] [[Kategorie:Beleuchtung]] 3bbda238fb854f0dd3f73cfed8fb536ba0e9e586 Mini-LED-Treiber 0 470 1742 1155 2021-12-23T14:38:53Z Chris 2 wikitext text/x-wiki [[Datei:mleddrv.jpg|thumb|Aufgebauter LED-Treiber]] Bei der [[Briefkasteninnenbeleuchtung]] habe ich gemerkt, dass ich keine kompakten LED-Treiber herumliegen habe. Zwar ist eine Konstantstromquelle sehr einfach auf Lochraster oder auch fliegend aufgebaut, aber leider ist die Schaltung dann entweder groß oder mechanisch empfindlich. =Funktionsweise= Die Schaltung und die Idee dahinter ist weder kompliziert noch neu. Im Gegenteil dürfte sie sogar ein gutes Beispiel aus dem Lehrbuch sein. <gallery> mleddrv_sch.png|Schaltplan </gallery> Sie kann wahlweise mit zwei Bipolar-Transistoren oder mit zumindest einem FET aufgebaut werden. Das Prinzip ist wie folgt: steigt die Spannung an der Basis eines Bipolar-Transistors über dessen Basis-Emitter-Spannung, wird dieser gemäß seiner Stromverstärkung zwischen Kollektor und Emitter leitend. Erzeugt man diese Spannung über einen Widerstand, kann man über dessen Wert den Strom definieren, ab dem der Transistor leitend wird. Üblicherweise liegt die U<sub>BE</sub> eines BC548 bei 0,6 V. Möchte man, dass dieser bei 5 mA leitend wird, muss am Widerstand eben diese Spannung abfallen. R = U/I ergibt 120 Ohm. Das ist schon einmal die halbe Miete. Jetzt muss diese Regelgröße nur noch zurückgeführt werden. Hier hilft ein zweiter Transistor, der in Serie zur LED geschalten wird. Der Transistor muss nun so angesteuert werden, dass er, wenn die Spannung (und damit der Strom) am Widerstand höher wird, weniger Strom durchlässt. Spannung hoch: Strom hoch, Spannung runter: Strom runter. Genau das macht unser "Messtransistor", wenn man ihm einen Pull-up am Emitter spendiert. In ein paar Beziehungen kann man die Schaltung verbessern: ersetzt man den "Regeltransistor" durch einen n-Kanal-FET, gewinnt man zwei Dinge: zum einen kann der Pull-up-Widerstand deutlich größer dimensioniert werden: FETs benötigen im Gegensatz zu Bipolar-Transistoren keinen nennenswerten Strom am Gate; zum anderen entfällt die Kollektor-Emitter-Spannung, bzw. wird durch den R<sub>ds,on</sub> des FET ersetzt, was sich positiv auf die minimale Betriebsspannung auswirkt. Ferner muss der Pull-up des oberen ("Regel-")Transistors nicht unbedingt direkt an der Versorgung angeschlossen werden, dieser kann zum Schalten der Konstantstromquelle genutzt werden. Da die Stromregelung relativ schnell ist, kann die Leitung problemlos zum Dimmen per PWM genutzt werden. =Layout= Je kleiner, desto besser - allerdings sollte es auch noch per Hand lötbar sein. Deshalb kommen die im SOT-23-Gehäuse verfügbaren Transistoren BSS138 und BC848 zum Einsatz. Bei den Widerständen reichen welche im 0603-Gehäuse. Um den Platz effektiv nutzen zu können, habe ich zwei Varianten erstellt: eine einseitig und beidseitig bestückbare: <gallery> mleddrv_brd_single.png|Einseitit bestücktes Layout mleddrv_brd_double.png|Zweiseitig bestücktes Layout </gallery> =Leistungsfähigkeit= Widerstände 0603-Gehäuse können in aller Regel 100 mW ab. Das klingt nach nicht sehr viel, reicht aber für die meisten nicht-High-Power-LEDs. Wie oben beschrieben, fallen über den Widerstand ca. 0,65 V ab, mit I = P/U ergibt das einen Strom von 154 mA - da kann man schon fast von "High Power" sprechen. Der begrenzende Faktor liegt aber meist woanders. Der "obere" der Transistoren stellt den Strom ein, über ihn fällt somit Spannungsdifferenz zwischen Eingangsspannung und der Vorwärtsspannung der LED sowie den Spannungsabfall über den Messwiderstand ab. Die Leistung in diesem Transistor berechnet sich zu :<math>P = (U - U_\textrm{f} - U_\textrm{BE}) \cdot I_\textrm{LED}</math> Würde man eine weiße LED (U<sub>LED</sub> = ca. 3,2 V) mit 100 mA und einer Eingangsspannung von 12 V treiben wollen, würde der Transistor stolze 0,8 Watt verbraten. Das wird mit Sicherheit nichts. Im Datenblatt des BSS138 steht eine maximale Leistung von 0,36 Watt und ein Derating von 2,8 mW pro °C. YMMV. Mit diesen Informationen kann man Kennlinienfelder zeichnen - ich hab da schon mal was vorbereitet: <gallery> mleddrv_Kennlinien.png|Kennlinienfeld des LED-Treibers </gallery> Wer das Lesen von Kennlinienfeldern nicht gewohnt ist, hier eine kleine Erläuterung: Zunächst sucht man sich eine Kennlinie aus - für die oben genannte weiße LED wäre das die durchgehend Schwarze. Nun kann man entweder von unten oder links lesen, je nachdem, welchen Wert man sucht. Will man die LED mit 100 mA treiben, sucht man sich auf der Y-Achse die 100 und findet den Schnittpunkt mit der schwarzen Kennlinie. An dieser hangelt man sich nach unten und liest die dazugehörende maximale Betriebsspannung ab: 6,7nochwas Volt. Andersrum: Bei einer Betriebsspannung von 12 V geht man nach oben, wiederum zum Schnittpunkt und dann nach links: irgendwas zwischen 35 und 40 mA. Die Linien im Diagramm sind nicht zufällig gewählt - diese entsprechen in etwa den Vorwärtsspannungen der LEDs in den jeweiligen Farben (schwarz für weiße LEDs, gelbe und orange entsprechen etwa den grünen). Die gestrichelten Linien entsprechen der Reihenschaltung von zwei LEDs der entsprechenden Farbe. Hier sieht man auch, dass durch den höheren Spannungsabfall an den LEDs der Spannungsabfall am Transistor fällt und dadurch höhere Betriebsspannungen möglich werden. Zum Eingangsspannungsbereich kann ich nicht viel sagen, außer dass dieser etwa mindestens so groß wie die LED-Vorwärtsspannung + 0,7 V sein sollte. Das obere Ende wird durch die Transistoren begrenzt. Beim BSS138 wäre das theoretisch die LED-Spannung + 50 Volt. Vorher gibt es aber sicher thermische Probleme. =Download= [[Datei:mleddrv.zip|Schaltplan, Layout, Excel-Datei mit Kennlinienfeld, LtSpice-Daten zum Spielen]] Schaltplan, Layout, Excel-Datei mit Kennlinienfeld, LtSpice-Daten zum Spielen [[Kategorie:Elektronik]] [[Kategorie:Kleine Helferlein]] [[Kategorie:Beleuchtung]] 99450921a5965be8457ed9a37d7feae860202d1d Reparatur iTP A3 EOS 0 385 1743 1048 2021-12-23T14:39:04Z Chris 2 wikitext text/x-wiki [[Datei:iTP_Gesamt.jpg|thumb|iTP A3 EOS im Vergleich zu einer AA-Zelle]] Vor ein paar Jahren habe ich mir eine iTP A3 EOS (upgraded) zugelegt. Wem die Bezeichnung nichts sagt: keine Sorge, muss man nicht kennen - es handelt sich dabei um eine Taschenlampe. Sie hat bis zu 96 Lumen (in 3 Stufen), obwohl sie nicht besonders größer als eine AA-Batterie ist (14 mm Durchmesser, 67 mm lang). Versorgt wird sie durch eine einzelne AAA-Zelle wobei der eingebaute Schaltwandler bis knapp 0,9 Volt läuft. Er holt also fast alles aus der Zelle, auch wenn die Taschenlampe zum Ende hin etwas dunkler wird. Das Teil ist - wie so vieles - toll, solange es funktioniert. Nachdem das Lämpchen immer am Schlüsselbund ist und dementsprechend öfter mal runter fiel, war nach knapp drei Jahren Schluss. Erst ging sie erst nach zudrehen und anschnippen an, später musste man etwas klopfen, dann blieb sie dauerhaft aus. Grmpf. Wegwerfen? Auf keinen Fall! Zumal es sie anscheinend nicht mehr zu Kaufen gibt. = Auf das Ding! = Das wahrscheinlich schwierigste Unterfangen an der Reparatur - Der Kopf der Lampe ist schnell drunten, aber wie kommt man an die Elektronik? Zwei Löcher in der Leiterkarte und das Gewinde verraten den Trick: Rausschrauben. Dazu nimmt man am besten eine ältere und sehr stabile Pinzette oder spannt zwei passende Stahlstifte (am besten mit Absatz oder konisch, damit man innen nichts aufspießt) in einen Schraubstock. <gallery> Datei:iTP_Kopf.jpg|Taschenlampenkopf von hinten Datei:iTP_oeffnen.jpg|Einrasten & Drehen </gallery> Erschwerend kommt dazu, dass der Innenkörper mit dem Lampenkopf verklebt wurde. Dagegen arbeitet man am besten mit Wärme und sanfter Gewalt. Es hilft auch, den Innenkörper immer wieder ein Stück hineinzudrehen. Hat man das Innenleben befreit, ist es empfehlenswert, die Klebereste vollständig zu entfernen - sowohl am Innenteil als auch am Lampenkopf. Sonst wird das Einschrauben später noch schwieriger. Dazu am Besten wieder erwärmen und vorsichtig (das Alu ist relativ weich) die Gewindegänge auskratzen. <gallery> Datei:iTP_Innenkoerper_oben.jpg|Helle Seite... Datei:iTP_Innenkoerper_unten.jpg|...und dunkle Seite des Innenkörpers </gallery> Um an die Elektronik zu kommen, muss zunächst die Leiterkarte runter, die zugleich den Kontakt zur Batterie darstellt. Dazu geht man am besten mit einem feinen Schraubendreher in die Nut und hebelt sie vorsichtig heraus. Wärme hilft auch hier gegen den Kleber. Oft sieht man nach diesem Schritt schon den Defekt: <gallery> Datei:iTP_Leitungsbruch1.jpg Datei:iTP_Leitungsbruch2.jpg Datei:iTP_Leitungsbruch3.jpg </gallery> Leitungsbruch. = Reparatur = Damit das Löten einfacher vonstatten geht (es ist verdammt eng!) habe ich bei meinen beiden Reparaturen auch die LED herausgenommen. Dazu muss man auf der anderen Seite des Innenteils zuerst die Plastikabdeckung herausnehmen und anschließend die Anschlussdrähte ablöten. <gallery> Datei:iTP_LED1.jpg|Mit Deckel Datei:iTP_LED2.jpg|Ohne Deckel Datei:ITP Waermeleitpaste.jpg|Ohne LED aber mit Pampe Datei:iTP_LED3.jpg|Ohne LED und Pampe </gallery> Da die Wärmeleitpaste eh eingetrocknet ist, kann man sie auch gleich entfernen/erneuern. Isopropanol und Wattestäbchen sind hier die Mittel der Wahl. Wenn man das Teil schon einmal offen hat: Am besten beide Leitungen zum Batteriekontakt tauschen! Ich habe bei der ersten Reparatur vor einem halben Jahr den Fehler gemacht, nur die gebrochene Leitung neu anzulöten und durfte das Teil jetzt noch einmal öffnen. Die beiden Litzen sind recht kurz zu halten, 1 cm ist mehr als genug. Auf jeden Fall sollte man eine feine Litze nehmen (meine ist schon fast zu dick), damit die Lötstellen nicht wieder so schnell brechen. = Zusammenbau = Und schon liegt das Teil wieder da wie eine aufgebrachte Krabbe - bis man es wieder in die Behausung steckt: <gallery> Datei:iTP_Zusammenbau1.jpg|[http://www.youtube.com/results?search_query=findet+nemo+krabben+hey Hey!] Datei:iTP_Zusammenbau2.jpg|Zusammengeklappt Datei:iTP_Zusammenbau3.jpg|und wieder eingebaut </gallery> Wichtig beim Zusammenbau: die Drähte für die LED durch die Löcher stecken und dann die Elektronik um 180 Grad drehen, sonst schauen die Drähte viel zu weit heraus. (Alternativ: zuerst LED anlöten und dann die Elektronik ins Alugehäuse einsetzen) Die vorher entfernte Wärmeleitpaste durch neue ersetzt (wie beim PC gilt: weniger ist manchmal mehr und bei mir ist es fast schon zu viel) und schon kann man die LED wieder anlöten. Beim Anlöten der Drähte an die LED müssen diese gegen den Uhrzeigersinn liegen (siehe oben), sonst passt die Plastikkappe nicht! Bei der LED sind übrigens sowohl Anode als auch Kathode auf der Trägerplatine markiert (+ und -) Die Kontaktplatine wieder eingedrückt (wenn sie fest hält, muss man sie nicht einmal verkleben) kann das Modul wieder ins Gehäuse. Und sie leuchtet wieder! [[Kategorie:Elektronik]] [[Kategorie:Reparatur]] [[Kategorie:Beleuchtung]] a7db70193e3555de45d32ed40adb1f96b3b88e62 Touchlight 0 92 1744 712 2021-12-23T14:39:17Z Chris 2 wikitext text/x-wiki {{Infobox AVR | Typ = ATtiny13 | Takt = 9,6 | FuseH = FF | FuseL = 7A }} Nach der etwas [http://hobbyelektronik.org/b/?p=15 unfreiwilligen Umräumaktion] in meinem Zimmer brauchte ich eine neue Nachttischlampe. Problem: ich hab am neuen Platz keine geeignete Stellfläche. An der Kopfseite vom Bett ist aufgrund der Fußleiste ein Abstand von knapp 2cm zur Wand. Dieser lädt irgendwie dazu ein, eine indirekte Beleuchtung einzubauen. Die erste Idee war, Leuchtstoffröhren bzw. CCFLs dort zu verstecken. Das Pfeifen der meist billigen Inverter, die Wärmeentwicklung und auch die Spannung/HF waren für den Einsatzzweck doch nicht allzu vertrauenserweckend. = Leuchtmittel = Zum Glück sind LEDs mittlerweile hell genug, dass sie sich für soetwas lohnen, allerdings sind die weißen doch noch ein bisschen teuer. Vor ein paar Wochen bin ich dann bei eBay über ein Angebot gestoßen: 100 "ultrahelle weiße LEDs" für 9 Euro inkl. Versand aus Thailand - also 9ct pro LED. Für den Preis steht bei Conrad noch nicht einmal jemand auf, um eine solche zu holen. Nach ein paar Tagen waren die LEDs dann tatsächlich hier. Zwar haben sie eine gewisse Farb- und Helligkeitsstreuung, dafür kann man sie bei der Menge problemlos selektieren. Damit die Beleuchtung etwas angenehmer wird, soll sie dimmbar werden. Das soll ein kleiner Atmel Tiny13 übernehmen, der über zwei Hardware-PWMs verfügt. Um diese auch nutzen zu können, wird die LED-Leiste in zwei Stränge unterteilt. Die Anzahl der LEDs wird einzig durch das Netzteil beschränkt (ein austemustertes SonyEricsson-Ladegerät). Da dieses etwas über 400mA zur Verfügung stellt, kommen 22 Dioden (á 20mA) auf die Acrylplatten. = Bedienung = Da sich der kleine AVR nur mit PWM langweilt, soll statt konventionellen Tastern etwas moderneres zum Einsatz kommen: berührungsempfindliche Sensoren. Problem: Die Controller für Touchpads sind entweder teuer oder schwer zu beschafen. Es gibt zwar haufenweise Code für AVRs, mit denen man das Ganze in Software machen kann. Bis jetzt ist mir aber noch keine über den Weg gelaufen, die bei mir richtig funktioniert hat. Ok, eine ([http://www.dietmar-schroeder.de/schaltungstechnik.html#kanmi2 von Zabex]) hat funktioniert, diese braucht allerdings je Sensor zwei Pins, was bei dem AVR mit aktiviertem Reset-Pin (schließlich soll das Teil weiterhin mit ISP programmiert werden können) etwas schwierig wird. = Theorie = [[Bild:Touchlight_Ladekurve.png|thumb|Ladekurve am Kondensator]] [[Bild:Touchlight_Schem.png|thumb|Stromlaufplan der Schaltung]] Aber erst einmal zur Theorie, wie ein einfacher Sensor funktionieren soll. Die Spannung an einem Kondensator verhält sich beim Laden wie folgt: <!--U_{(t)}=U_0\cdot(1-\mathit{e}^\frac{-t}{R_1 \cdot C})--> :<math>U\left(t\right) = U_{0} \cdot \left(1-e^{\frac{-t}{R \cdot C}}\right)</math> Die Formel ist (dadurch, dass ich hier kein TeX hab') etwas unschön. U(t) ist die Spannung am Kondensator abhängig von der Zeit, U0 die Ladespannung, e die Eulersche Zahl, t die der Zeitpunkt nach Ladebeginn, R der Ladewiderstand und C die Kapazität des Kondensators. Die Portpins an Mikrocontrollern haben gegenüber GND eine nicht allzu hohe Kapazität. Legt man einen großen Widerstand an einen Portpin kann man die Zeit, bis der Spannungspegel als High erkannt wird, jedoch relativ gut messen. Dieser Pegel liegt bei den meisten AVRs bei 5V Betriebsspannung bei etwa 1,9V (im Datenblatt nach "Pin Thresholds and Hysteresis" suchen). Schließt man jetzt an den Port-Pin eine Metallplatte an, verändert sich zunächst nicht viel an der Kapazität, bringt man allerdings einen größeren (leitenden) Gegenstand in die Nähe bzw. berührt sie damit, verändert sich die Kapazität am Port-Pin - es dauert länger, bis der Pin geladen ist. '''Achtung:''' der Pin, an dem gemessen wird, ist anfälliger für ESD-Schäden! Aus diesem Grund sollte ein Widerstand (~1k) in Reihe zur Metallplatte angebracht werden! Weiter sollte die Metallplatte mit einer Folie bzw. Lack isoliert werden. Dadurch sinkt zwar die Empfindlichkeit, allerdings kann man die Andruckstärke/-fläche besser messen. Bei Berührung der Metallplatte dauert es etwa 60µs, bis der Pin bei 1MOhm-Ladewiderstand die Schwellenspannung erreicht hat. Ohne dauert es etwas länger (genaue Zahlen kann ich momentan nicht sagen), wenn kein Finger an der Schaltung anliegt. = Praxis = Um es noch ein wenig anschaulicher zu machen, habe ich das Oszilloskop auf die Schaltung angesetzt. Dazu wurde die Schaltung auf dem Breadboard aufgebaut. Die Ladewiderstände entsprechen wie im Schaltplan 1,1MOhm. Die Sensorfläche mit 28x28mm (7,8 cm²) und 1,5mm Dicke (Dielektrikum: Hartpapier) ist mit 5cm Leitung direkt (ohne Angstwiderstand) mit dem AVR verbunden. Aufgrund der nicht zu verachtenden Kapazität des Breadboards un des Tastkopfes (Impedanz weiß ich gerade nicht auswendig) dürften die Messwerte deutlich verzerrt sein! Die Bilder und Erklärungen dienen daher höchstens zum Veranschaulichen des vorherigen Abschnitts! <gallery> Bild:Touchlight untouched.png|Unberührte Sensorfläche Bild:Touchlight touched.png|Berührte Sensorfläche Bild:Touchlight burst untuched.png|"Abfrageburst" unberührt Bild:Touchlight burst touched.png|"Abfrageburst" berührt </gallery> Im ersten Bild ist der Spannungsverlauf zu sehen, bei dem die Sensorfläche nicht berührt wurde. Entgegen der Datenblattangabe erkennt der AVR den High-Pegel bei 2,58V, wobei es 26,6µs dauert, bis dieser Wert erreicht wird. Wird die komplette Sensorfläche mit der Hand abgedeckt, steigt die Dauer bis zum Schwellenwert auf 41µs, also etwa das 1,5-fache der Zeit der unberührten Sensorfläche. Bei einem CPU-Takt von 9,6MHz sind dies 394 Taktzyklen (im Vergleich zu 256 Taktzyklen vorher), die man recht entspannt messen kann. In den letzten beiden Bildern ist ein kompletter "Abfrageburst" (5 Einzelabfragen) zu sehen. Auch wenn es auf den ersten Blick irreführend ist, die Bildunterschriften sind korrekt. Bei den beiden Fotos habe ich (dummerweise) eine andere Zeitbasis gewählt. Auch bei den Bursts hat das Zeitverhältnis zwischen unberührt und berührt den Faktor 1,5. Wobei ich dazu sagen muss: '''Traue keiner Statistik, die du nicht selbst gefälscht hast!''' Die gemessenen Dauern schwanken insbesondere beim Berühren der Sensorfläche immens. Hauptursache dürfte wahrscheinlich der Elektrosmog sein, der die 50 bzw. 100Hz (Halbwellen) aus dem Stromnetz beisteuert... = Die Software = Bei der Software muss man außer warten eigentlich nicht viel machen. Vor der Messung muss der Pin lediglich komplett entladen sein. Das erreicht man, indem man den Pin als Ausgang schaltet und den Pegel auf Low setzt. Zum Starten der Messung muss nun lediglich der Pin auf Eingang umgestellt werden. Der interne Pull-Up '''muss''' aus bleiben! In diesem Zustand kann nun der externe Pull-Up den Port langsam laden - nun kann mit einer einfachen Schleife die Zeit gemessen werden: <geshi lang=c> uint8_t getcap(uint8_t pin, uint8_t sampletime, uint8_t waittime) { KEYDDR &= ~pin; //Pin als Eingang -> laden lassen while(waittime--) { nop(); } //etwas Zeit verstreichen while(!(KEYPIN & pin) && --sampletime); //Zeit messen KEYDDR |= pin; //Pin als Ausgang -> entladen return sampletime; } </geshi> Das ist im Prinzip auch schon alles. Bei einer Sensorfläche von 4cm² war (bei 9,6MHz Takt des Tiny13) sampletime 50 und waittime 40. Waittime sollte so gesetzt werden, dass sich der Rückgabewert ohne Berührung des Pads nicht verändert. Sampletime sollte so gewählt werden, dass bei vollflächiger Berührung der Wert 0 erreicht wird. So kann man die Fläche und Andruckstärke der Berührung relativ gut ermitteln. Mit zwei einfachen ifs kann man nun einen simplen Sensortaster bauen: <geshi lang=c> ... i = 0; n = 6; while(--n) { i += getcap(1<<PB3, 50, 40); } i /= 5; if(i < 42) { PORTB |= (1<<PB2); } else if(i > 45) { PORTB &= ~(1<<PB2); } ... </geshi> Man beachte die Hysterese zwischen An- und Ausschaltwert. Ohne diesen kleinen Abstand flackert die LED, wenn das Sensorfläche nur zu einem bestimmten Grad berührt wird. Die Kapazität wird in diesem Beispiel 5 mal gemessen, um Ausreißer zu vermeiden. Soweit lieb und nett, aber wer möchte seinen Finger auf einem Schalter halten, um Licht zu bekommen? Über einen zweiten Sensor kann man zwar einen Ein- und Ausschalter implementieren, aber warum mit wenig zufriedengeben? == Dimmer == [[Bild:Touchlight_Helligkeit.png|thumb|Helligkeitsverlauf]] Nachdem der Tiny13, wie bereits erwähnt, zwei PWMs sein eigen nennt, ist ein Dimmer eigentlich sehr schnell gebaut. Über die Register OCR0A und OCR0B kann direkt das On-Off-Verhältnis an den Ausgängen eingestellt werden. Die Sensoren werden als Up-Down-Taster umfunktioniert und schon kann man durch Handauflegen hell und dunkel machen. Allerdings ist der Helligkeitsverlauf für das menschliche Auge etwas unangenehm. Da menschliche Wahrnehmungen diesbezüglich logarithmisch ist, darf die Helligkeit nicht linear verändert werden, sondern muss einer Exponentialfunktion folgen. Also in der Tabellenkalkulation Pi mal Daumen eine E-Funktion ausgeben lassen und markante Punkte markiert. Mit Hilfe der X- und Y-Koordinaten kann nun im Programm die Helligkeit bestimmt werden. Die Punkte wurden so gewählt, dass der Verlauf zwischen ihnen möglichst linear ist - somit können die Zwischenwerte ermittelt werden, ohne dass es wirklich auffällt. Bleibt nur noch ein kleines Problem: Man sieht besonders bei den niedrigen Helligkeiten Stufen beim Dimmen, das ist etwas störend. Abhilfe schafft der zweite PWM. Da die LED-Leisten sowieso in zwei Stränge aufgeteilt sind, können weitere Helligkeitswerte simuliert werden. Die Verteilung der Helligkeit auf zwei Kanäle ist recht einfach: <geshi lang=c> uint16_t tmp = GetPwm((uint16_t)brightness); uint16_t ba = tmp / 2; uint16_t bb = tmp - ba; </geshi> Ist zwar nicht sonderlich schön, funktioniert dafür aber recht gut. == Download == [[Datei:Touch_1.0.zip]] Enthält sowohl den simplen Touchsensor als auch die Version mit serieller Ausgabe. CPU-Takt muss jeweils 9,6MHz sein (Bei Fabrikneuen Tiny13ern muss die CKDIV8-Fuse entfernt werden, damit das Teil bei vollem Takt läuft), der Rest nach eigenem Ermessen. Stromlaufpläne ist bei beiden Sourcen gleich, bei TouchSense ist zusätzlich der (nicht-invertierte) UART auf PBO. Dort werden die Messwerte der beiden Sensoren Tab-getrennt ausgegeben. die Konstante MINDELAY für den UART-Pause in suart.c muss wahrscheinlich angepasst werden. [[Category:AVR]] [[Kategorie:Beleuchtung]] db31a65d0934778d272ee14b269018da91058d34 LED-Lagerfeuer 0 767 1745 1738 2021-12-23T14:49:55Z Chris 2 /* Ergebnis */ wikitext text/x-wiki Mein Vater stellt in der lokalen Dorfkirche jedes Jahr zu Weihnachten die Krippe auf. Diese wurde um 1920 gebaut und vermutlich stammt ein Teil der verbauten Beleuchtung noch von damals. Durch das Alter und dem Übersommern in einer einfachen freistehenden Garage ist die Installation mittlerweile etwas morsch: <gallery> Feuer_alte_Leitung.jpg | Alte Leitung </gallery> Aus diesem Grund sollte der Aufbau ein bisschen auf Vordermann gebracht werden. =Ausgangssituation= Auf der Haben-Seite steht die Krippe mit 60 Watt Glühobst im Stall und einer vermutlich 5 Watt-Funzel im Hirtenfeuer, die diesem mit einem Pergamentpapier ein rotes Ambiente verpasst. Beim Soll gibt es hauptsächlich den Punkt "soll nicht abbrennen", zumal sehr viel trockenes Moos und brennbares Material werwendet ist. =Lösung= Aufgrund der niedrigen Spannung und der breiten Verfügbarkeit wird die Versorgung auf USB umgestellt. ==Stallbeleuchtung== Im Lager liegt noch ein 10 cm langes COB-LED-Modul herum, das schon seinen Platz auf einem Kühlkörper gefunden hat. Da es mit 12 V versorgt werden muss, kommt noch ein [Reparatur_R&S_CMU200_Hintergrundbeleuchtung#LED-Treiber|Boost-Konverter] davor - mit dem netten Nebeneffekt, dass man die Helligkeit je nach Bedarf einstellen kann. ==Hirtenfeuer== Auch hier könnte es im einfachsten Fall ein direkter Ersatz mit einer weißen LED sein - aber das wäre langweilig. ===Hardware=== Stattdessen sind auf einer Punktraster-Leiterkarte 22 SMD-LEDs gelandet, 6 davon orange, der Rest rot. Alle LEDs sind in Strängen von zwei angeordnet, wobei ein paar Stränge parallel geschaltet sind - aus dem einfachen Grund, dass ich nicht mehr als 8 Kanäle implementieren wollte. Mit jeweils 2 LEDs in Reihe und einem Strom von etwa 7,5 mA kamen jeweils Widerstände mit 160 Ohm in Reihe. Auf der anderen Seite der Leiterkarte sitzt ein ATtiny44A und eine Bank an BSS138. Zwar hätte der Mikrocontroller die Ketten direkt treiben können, allerdings ist der Strom in Summe über dem, den er abkann. Zusätzlich finden noch Abblockkondensatoren und eine ESD-Diode. Einen Schaltplan aufgrund der Einfachheit gibt es nicht, alle LEDs (bzw. die zugehörigen Transistoren) sind an PORTA angeschlossen. <gallery> Feuer_top.jpg | LED-Seite Feuer_bot.jpg | Mikrocontroller und Peripherie Feuer_top_on.jpg | Beleuchtung aktiv </gallery> ===Firmware=== {{Infobox AVR | Typ = ATTiny44A | Takt = 8 | FuseH = DF | FuseL = E2 | FuseE = FF }} Wie programmiert man ein Feuer, das eher ruhig glimmt anstatt lodernde Flamen zu speien? Mein erster Ansatz war: Zufall. Die Helligkeiten werden in einem festen Zeitraster mit einem zufälligen Wert beschrieben. Nicht so richtig schlecht, aber eben auch nicht so richtig gut. Da die Firmware eh ein Aufguss von [[Anykey x6]] ist, kommt die Fading-"Engine" dazu, für die die Dauer ebenfalls zufällig gewählt wird. Die <code>main</code>-Funktion sieht dann wie folgt aus: <source lang="c"> int main(void) { wdt_enable(WDTO_1S); leddrv_init(); fader_init(); uint16_t postscale = 0; //pwm: ca. 469 Hz while (1) { bool update = leddrv_poll(); if(update == true) { postscale++; if(postscale == 1000) { //ca. 69 Hz. (nice) fader_tick(); postscale = 0; for(uint8_t i = 0; i < 8; i++) { if(fader_running(i) == false) { wdt_reset(); uint8_t d = rand() & 0x4F; uint8_t b = rand(); fader_set(i, b, d); } } wdt_reset(); } } } } </source> Die Zeiten in den Kommentaren sind eher Richtwerte, da der interne Oszillator nicht unbedingt genau ist. ===Ergebnis=== Das Ergebnis kann sich durchaus sehen lassen. Als Beispiel habe ich einfach mal zwei Clips aufgenommen: * [https://youtu.be/99Q9R-xaIWI Direkter Blick, defokussiert] * [https://youtu.be/8LfEn3cYuh0 Durch eine Lage Zellstoff (Taschentuch)] In den Videos kann man den Unterschied zwischen roten und orangenen LEDs kaum unterscheiden, was auch - aber nicht nur - an der [[wpde:Farbunterabtastung|Farbunterabtastung]] der Aufnahme liegt. Der andere Grund: Die beiden Farben liegen bei den verwendeten Farben recht nah beieinander. Im Nachhinein hätte ich wohl eher einen Mix von 50:50 verwenden sollen. Eingebaut in das Lagerfeuer und ein bisschen Füllwatte für Kissen sieht das Lagerfeuer nun wie folgt aus: <gallery> Feuer_assy.jpg | Vorbereitetes Lagerfeuer </gallery> ==Sternenhimmel== Eher in einem Nebensatz erwähnte mein Vater (vielleicht auch da es eine andere Krippe in Familienbesitz hat), ob nicht ein Sternenhimmel ganz schön wäre. Nach dem obligatorisch-schwäbischen "wozu denn, gab's bis jetzt doch auch nicht", ging der Klick doch auf eBay. Das Lieferversprechen wurde gehalten und so konnte ich zwei Tage später (und einen Tag vor dem Aufbau) eine Drahtlichterkette mit 100 LEDs in den Händen halten. Mit einem auf ca. 10 mA eingestellten [[Mini-LED-Treiber]] sind die Leuchtdioden so hell, dass sie auch bei Umgebungslicht noch gut zu erkennen sind, aber die Umgebung nicht ausleuchten. Immer wieder erstaunlich, wie viel Licht bei nur 100 µA pro LED rauskommt. =Alles zusammen= Draußen ist kalt, bei der Hütte in der die Krippe steht gibt es keinen Strom (damit man den Lötkolben auspacken könnte) und gleichzeitig möchte ich nicht unnötig lange in der Kirche herumstehen - nicht nur, weil es die Arbeit der anderen verzögert. Deshalb soll alles "ready to use" sein. An den Enden der Stallbeleuchtung ist jeweils großzügig Schrumpfschlauch aufgezogen, gleiches beim Booster desselben - die "Schlapse" machen Bekanntschaft mit der Lochzange. Zack feddich: Montagelöcher. Am Booster ist zudem der Schraubenkopf des Poti freigeschnitten, damit die Helligkeit einfach eingestellt werden kann. Für das Lagerfeuer gibt es ca. 50 cm Leitung und den Versuch mit Dupont-Steckern einen Verpolschutz einzubauen. Im Nachhinein wäre vermutlich cleverer gewesen, Masse auf einen Stift und Versorgung auf die Buchse auf der einen Seite und entsprechend andersrum auf die andere Seite zu legen, aber mit angucken sollte auch das zu Schaffen sein. Den gleichen Konnektor gibt es für die Sterne. Da ich mehr generische 5 V- als USB-Netzteile herumliegen habe und sowieso eine USB-Verlängerung aufschneiden muss, wird der Hohlstecker geopfert und das weibliche Ende der Verlängerung angelötet. Um einem Herausrutschen und Ratlosigkeit entgegenzuwirken, lassen sich die USB-Stecker mit aufgeklebtem Klettband miteinander befestigen. Um den Fummelfaktor zu verringern, ist auf dem "oberen" Teil zusätzlich ein Stück Kabelbinder aufgeklebt. <gallery> Feuer_USB.jpg | USB-Stecker mit Klett-Verriegelung Feuer_powercon.jpg | "interne" Stromstecker der Krippe Feuer_Stall_beleuchtet.jpg | Beleuchteter Stall Feuer_installiert.jpg | Platzierte Feuerstelle </gallery> Wenn ich mal die Gelegenheit habe, kommen noch ein paar Fotos des vollen Assembles. =Download= * [[Datei:Lagerfeuer.zip]] Microchip Studio Projekt des Lagerfeuers [[Kategorie:AVR]] [[Kategorie:Modellbau]] [[Kategorie:Beleuchtung]] c208a41c5cdd9e6d99ed17779cf0f0e9ed34c0e3 Hobbyelektronik.org:Impressum 4 4 1746 1698 2022-01-03T09:14:10Z Chris 2 wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org For those who don't speak German: feel free to write me in English! Für Zuschriften auf deutsch: Das "du" wird bevorzugt :) Im Normalfall antworte ich innerhalb von 1-3 Tagen. Solltest du innerhalb einer Woche keine Antwort bekommen, prüfe bitte deinen Spamfilter oder schicke eine Erinnerung, manchmal geht auch bei mir etwas unter. E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung im Schnitt nur eine Konversation in 2-3 Jahren verschlüsselt stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Kommerzielle Anfragen= In den meisten Fällen lautet die Antwort schlicht "Nein". Wie weiter unten steht habe ich kein Interesse an Werbung oder "kommerzieller Kooperation". Entsprechende Anfragen werden ignoriert. Auch habe ich wenig Interesse, in meiner Freizeit an kommerziellen Projekten oder Produkten zu arbeiten. Dazu fehlen mir einfach Zeit und Ressourcen. Nicht unbedingt technisch, sondern vielmehr organisatorisch. Produkte auf den Markt zu bringen ist deutlich mehr als Hardware zusammenzuklatschen und vielleicht noch "ein bisschen" Software dafür zu entwickeln. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über eine E-Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Ich bitte aber, zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schneller (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwendet Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteht es einfach als Kompetenzübung und beachtet den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nichts durch finanzielle Mittel beeinflusst. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich, kann aber zu Darstellungsfehlern führen. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) a1d14ac0afb9eed05d0ec7a49da3e1279d6f6525 1747 1746 2022-01-03T09:18:38Z Chris 2 /* Fragen/Hilfe/Unterstützung */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org For those who don't speak German: feel free to write me in English! Für Zuschriften auf deutsch: Das "du" wird bevorzugt :) Im Normalfall antworte ich innerhalb von 1-3 Tagen. Solltest du innerhalb einer Woche keine Antwort bekommen, prüfe bitte deinen Spamfilter oder schicke eine Erinnerung, manchmal geht auch bei mir etwas unter. E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung im Schnitt nur eine Konversation in 2-3 Jahren verschlüsselt stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Kommerzielle Anfragen= In den meisten Fällen lautet die Antwort schlicht "Nein". Wie weiter unten steht habe ich kein Interesse an Werbung oder "kommerzieller Kooperation". Entsprechende Anfragen werden ignoriert. Auch habe ich wenig Interesse, in meiner Freizeit an kommerziellen Projekten oder Produkten zu arbeiten. Dazu fehlen mir einfach Zeit und Ressourcen. Nicht unbedingt technisch, sondern vielmehr organisatorisch. Produkte auf den Markt zu bringen ist deutlich mehr als Hardware zusammenzuklatschen und vielleicht noch "ein bisschen" Software dafür zu entwickeln. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über jede Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Bitte jedoch zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup sowie die verfügbaren Mittel in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schneller (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwende Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteh es einfach als Kompetenzübung und beachte den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nichts durch finanzielle Mittel beeinflusst. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog hier oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich, kann aber zu Darstellungsfehlern führen. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) 2bd93f4c5221955fc138d9de8acad7385d9fda26 1748 1747 2022-01-03T09:19:55Z Chris 2 /* Spenden */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org For those who don't speak German: feel free to write me in English! Für Zuschriften auf deutsch: Das "du" wird bevorzugt :) Im Normalfall antworte ich innerhalb von 1-3 Tagen. Solltest du innerhalb einer Woche keine Antwort bekommen, prüfe bitte deinen Spamfilter oder schicke eine Erinnerung, manchmal geht auch bei mir etwas unter. E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung im Schnitt nur eine Konversation in 2-3 Jahren verschlüsselt stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Kommerzielle Anfragen= In den meisten Fällen lautet die Antwort schlicht "Nein". Wie weiter unten steht habe ich kein Interesse an Werbung oder "kommerzieller Kooperation". Entsprechende Anfragen werden ignoriert. Auch habe ich wenig Interesse, in meiner Freizeit an kommerziellen Projekten oder Produkten zu arbeiten. Dazu fehlen mir einfach Zeit und Ressourcen. Nicht unbedingt technisch, sondern vielmehr organisatorisch. Produkte auf den Markt zu bringen ist deutlich mehr als Hardware zusammenzuklatschen und vielleicht noch "ein bisschen" Software dafür zu entwickeln. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über jede Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Bitte jedoch zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup sowie die verfügbaren Mittel in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schneller (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwende Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteh es einfach als Kompetenzübung und beachte den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nichts durch finanzielle Mittel beeinflusst. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird beim genaueren Blick im Blog oder im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich geantwortet, dass die das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich, kann aber zu Darstellungsfehlern führen. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) b557e111979f74713fdf20da629820b2f0e981f1 1760 1748 2022-06-09T19:30:51Z Chris 2 /* Spenden */ Typos korrigiert wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org For those who don't speak German: feel free to write me in English! Für Zuschriften auf deutsch: Das "du" wird bevorzugt :) Im Normalfall antworte ich innerhalb von 1-3 Tagen. Solltest du innerhalb einer Woche keine Antwort bekommen, prüfe bitte deinen Spamfilter oder schicke eine Erinnerung, manchmal geht auch bei mir etwas unter. E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung im Schnitt nur eine Konversation in 2-3 Jahren verschlüsselt stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Kommerzielle Anfragen= In den meisten Fällen lautet die Antwort schlicht "Nein". Wie weiter unten steht habe ich kein Interesse an Werbung oder "kommerzieller Kooperation". Entsprechende Anfragen werden ignoriert. Auch habe ich wenig Interesse, in meiner Freizeit an kommerziellen Projekten oder Produkten zu arbeiten. Dazu fehlen mir einfach Zeit und Ressourcen. Nicht unbedingt technisch, sondern vielmehr organisatorisch. Produkte auf den Markt zu bringen ist deutlich mehr als Hardware zusammenzuklatschen und vielleicht noch "ein bisschen" Software dafür zu entwickeln. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über jede Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Bitte jedoch zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup sowie die verfügbaren Mittel in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schneller (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwende Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteh es einfach als Kompetenzübung und beachte den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nichts durch finanzielle Mittel beeinflusst. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird man beim genaueren Blick ins Blog oder ins Wiki bzw. hier im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich immer wieder geantwortet, dass sie das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen (wie Freifunk, z. B. [http://freifunk-unterstuetzungsverein.de/ hier in Ulm]) sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich, kann aber zu Darstellungsfehlern führen. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) baaf826ba63e82003ec10c3c12896aa5e5a2e94e VBus-Decoder/Adapter für den ESP8266 0 757 1749 1728 2022-02-05T20:51:40Z Chris 2 BOMs korrigiert wikitext text/x-wiki [[Bild:vbusesp_top.jpg|thumb|Aufgebauter Leiterkarte (v0.1)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Wenn Basteln und IoT aufeinandertreffen, kommt man fast nicht an den Mikrocontrollern von Espressif vorbei. Genau aus diesem Grund hatte ich schon länger die Idee, ein Leiterkärtchen mit dem ESP8266 zu machen. Also warum nicht einfach den beliebten VBus ohne großes Strippenziehen ins Netzwerk bringen? =Schaltung= Die Schaltung für den VBus basiert auf der für den [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Raspi (v1.3)]], aufseiten des ESP habe ich mich von den verschiedenen Bastelboards inspirieren lassen und die Möglichkeit vorgesehen, sowohl die kleinen ESP01- als auch die etwas vielseitigeren ESP12-Module einzusetzen. Die Versorgung findet über eine Stiftleiste (bzw. angelötete Drähte) oder über eine Micro-USB-Buchse statt. Diese dient nur der Stromversorgung - mehr zum Programmieren des ESP weiter unten. Bei der Verwendung des ESP12-Moduls stehen zusätzlich zum VBus-Interface noch die GPIOs 12, 13, 14 und 16 sowie der ADC-Eingang und die 3,3V-Versorgung zur Verfügung. Hier kann weitere Peripherie wie Sensoren oder Displays angeschlossen werden. Für den Aufbau gibt es mehrere Varianten, die unten aufgeführt sind. Diese können über die Tabs ausgewählt und müssen beim Besorgen der Bauteile und selbstverständlich beim Zusammenbau kombiniert werden. Die theoretische Maximalbestückung sieht wie folgt aus: <gallery> vbusesp_max_sch_1.png | Schaltplan VBus + Stromversorgung vbusesp_max_sch_2.png | Schaltplan ESP8266 und IO vbusesp_max_assy.png | Bestückungsplan </gallery> =BOM= Möglichkeiten schaffen Komplexität. Wie bei den anderen Plattformen lässt sich der Adapter in verschiedenen Varianten aufbauen, wobei ich (auch wenn es gerade bei dieser anbietet) noch immer empfehle, die Optoisolierte aufzubauen. ==Decoder== Neben Optoisoliert und Direkt gibt es noch die Variante ohne ESP - dank der Stiftleiste rechts oben auf der Leiterkarte lässt sich der VBus-Anteil komplett unabhängig vom ESP-Anteil verwenden. Mit Säge und Fingerspitzengefühl lässt sich die Größe auch noch ein gutes Stück reduzieren. Als ESP8266-Modul kann das ESP01 und ESP12(-F) verwendet werden. Getestet wurde bis jetzt nur das ESP12-F, wobei nichts gegen das 01 sprechen dürfte. <tabs> <tab name="Optoisoliert"> Empfohlene Bestückungsvariante. <gallery> vbusesp_optiso_sch_1.png | Variantenschaltplan VBus vbusesp_optiso_sch_2.png | Variantenschaltplan ESP8266 vbusesp_optiso_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 5 || R9, R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Direkt"> <gallery> vbusesp_direct_sch_1.png | Variantenschaltplan VBus vbusesp_direct_sch_2.png | Variantenschaltplan ESP8266 vbusesp_direct_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 4 || R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 2 || Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Optoisoliert (ohne ESP)"> Wer keinen ESP8266 verwenden aber die Vorzüge der verbesserten Schaltung haben möchte, kann den ESP-Anteil vollständig weglassen. Hierfür wird auf dieser Leiterkarte keine Stromversorgung benötigt, da diese vom jeweilig verwendeten Interface (z. B. SBC, USB-UART-Wandler, ...) bezogen werden kann. <gallery> vbusesp_optisonoesp_sch_1.png | Variantenschaltplan VBus vbusesp_optisonoesp_sch_2.png | Variantenschaltplan Interface vbusesp_optisonoesp_assy.png | Bestückungsplan vbusesp_vbusonly_pinout.png | Anschlussbelegung des UART </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> ==Stromversorgung== Für die Stromversorgung gibt es ebenfalls zwei Möglichkeiten: Entweder mit LDO oder Schaltwandler. Wer auf Nummer sicher gehen will, nimmt die billigere LDO-Variante, da ich noch keine Gelegenheit hatte letztere zu testen. Die etwas höhere Stromaufnahme dürfte wahrscheinlich nicht allzu sehr ins Gewicht fallen. <tabs> <tab name="Linearregler"> Empfohlene Bestückungsvariante. <gallery> vbusesp_vregldo_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregldo_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || REG1117 || SOT223 || NCP 1117 ST33T3G |} </tab> <tab name="Schaltwandler"> <gallery> vbusesp_vregsmps_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregsmps_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C9 || 100n || C0603 || X7R-G0603 100N |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C12 || 10p || C0603 || NPO-G0603 10P |- | 1 || R17 || 15k || R0603 || RND 0603 1 15K |- | 1 || L1 || 15u || 242408FPS || L-242408FPS 15µ |- | 1 || R16 || 47k || R0603 || RND 0603 1 47K |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || D6 || BAT43WS || SOD323-W || BAT 43WS |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || IC2 || MCP16301 || SOT23-6 || MCP 16301T-I/CHY |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || D4 || SS13L || SUBSMA || SS 13L |} </tab> </tabs> =Inbetriebnahme/Benutzung= ==Flashing== Wird ein ESP8266 verwendet, muss natürlich erst einmal die Software auf den Mikrocontroller. Das Problem: Der Softwaredownload findet über den selben UART statt, der auch für das VBus-Interface statt. Nun könnte man mit Multiplexern arbeiten, was im Idealfall nur einmal benutzt werden würde und somit mit Kanonen auf Spatzen geschossen wäre. Aus dem gleichen Grund gibt es keinen USB-UART-Konverter auf dem Board: Braucht nur Platz und kostet. Deshalb wird für das erstmalige Flashen ein USB-UART-Adapter, der RTS/DTR anbietet, benötigt. Dieser sollte idealerweise mit 3,3 V arbeite, wobei der ESP wohl auch 5 V toleriert. Die beiden Transistoren für Reset und Bootloader nach WittyCloud/NodeMCU sind bereits vorhanden. Die 5 V-Stromversorgung muss entweder über den USB-Port oder der Stiftleiste SV2 kommen, die Anschlussbelegung des UART an SV4 ist wie folgt: {| class="wikitable" ! Pin || Signal vom UART-Adapter |- | 1 || DTR |- | 3 || TX |- | 7 || RX |- | 9 || RTS |} <gallery> vbusesp_prog_1.png | Anschlussbelegung für das Programmieren per UART vbusesp_prog_2.jpg | Verwendung des WittyCloud-USB-Wandlers </gallery> Liegt das Trägerboard eines WittyCloud herum, müssen DTR und RTS gefädelt werden. ==Betrieb== Ist die Firmware auf dem Chip und es sollen Daten vom VBus decodiert werden, muss ein Jumper zwischen Pin 3 und 4 an SV4 oder ein Lötpunkt auf SJ1 gesetzt werden: <gallery> vbusesp_txjumper.png | UART-Verbindung zwischen VBus und ESP8266 </gallery> =Firmware= Zugegebenermaßen: ich habe zwar seit Jahren ein paar ESP8266-Module herumliegen, mich aber nie so richtig damit auseinandergesetzt. Aber das macht nichts: [https://tasmota.github.io/docs/ Tasmota] unterstützt verschiedene [https://tasmota.github.io/docs/Smart-Meter-Interface/ Smart Metering]-Anbindungen, für die die Firmware allerdings angepasst selbst kompiliert werden muss. Michael hat sich (mit der Unterstützung aus der Tasmota-Community) daran gemacht und freundlicherweise die nötigen Anpassungen zur Verfügung gestellt: Folgendes muss in der Datei <code>tasmota/user_config_override.h</code> ergänzt werden: <source lang="C"> #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ #ifndef USE_SCRIPT #define USE_SCRIPT #endif #ifndef USE_SML_M #define USE_SML_M #endif #ifdef USE_RULES #undef USE_RULES #endif #ifndef SML_REPLACE_VARS #define SML_REPLACE_VARS #endif #ifndef USE_SML_SCRIPT_CMD #define USE_SML_SCRIPT_CMD #endif #ifndef SML_MAX_VARS #define SML_MAX_VARS 20 #endif #ifndef USE_SCRIPT_JSON_EXPORT #define USE_SCRIPT_JSON_EXPORT #endif #ifndef USE_SCRIPT_WEB_DISPLAY #define USE_SCRIPT_WEB_DISPLAY #endif </source> ==Konfiguration== Nach dem Flashen des Mikrocontrollers, was für fertige Builds auch über den Tasmotizer erfolgen kann, kann unter <code>Main-Menu -> Console -> Edit Script</code> das [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus Script ergänzt] werden. Mit dem Befehl <code>sensor53 d1</code> kann man den Header für die [https://tasmota.github.io/docs/Smart-Meter-Interface/#meter-metrics Meter Metrics] ermitteln und im Script entsprechend anpassen. Für die RemaSol B/2 sieht das wie folgt aus: <source> r="1,aa10005d101000010a67" coltemp=0 Byte1=0 Byte2=0 >S coltemp=sml[1] Byte1=coltemp>>8 Byte2=coltemp&0xff if Byte1==0x00 { coltemp=coltemp&0xff } if Byte1==0xff { coltemp=(coltemp-0x10000) } coltemp=coltemp*0.1 >B =>sensor53 r >M 1 +1,3,v,0,9600,Solar %r%vo0uw@1,KollektorBase,°C,kolbase,2 %r%vo0uw@10,KollektorOrg,°C,kolorg,2 %r%vo2uw@10,Speicher unten,°C,spu,1 %r%vo4uw@10,Speicher oben,°C,spo,1 %r%vo8ub@1,Pumpe,%%,pump,0 # >J ,"Calculated":{"kol":%coltemp%} >W Kollektor berechnet: {m} %coltemp% °C </source> Anmerkung: Hierbei handelt es sich um einen direkten Copy & Paste aus Michaels Script. Je nach Konfiguration der Anlage kann es Abweichungen geben. Um den Fragen zuvorzukommen - die Anpassung auf die Jeweilige Anlage beginnt in der ersten Zeile: <code> r="1,<span class="hb1">aa</span><span class="hb2">1000</span><span class="hb3">5d10</span><span class="hb4">10</span><span class="hb5">0001</span><span class="hb6">0a</span><span class="hb7">67</span>" </code> Die Farben entsprechen dem Beispiel von der [[VBus-Decoder#Protokoll|Artikelhauptseite]], kurzum: * <span class="hb1">aa</span>: Sync-Wort * <span class="hb2">1000</span>: Zieladresse * <span class="hb3">5d10</span>: Quelladresse * <span class="hb4">10</span>: Protokollversion * <span class="hb5">0001</span>: Befehl * <span class="hb6">0a</span>: Anzahl Nutzdatenframes * <span class="hb7">67</span>: Prüfsumme Die <span class="hb3">Quelladresse</span> kann in der [https://danielwippermann.github.io/resol-vbus/#/vsf VBus-Spezifikation nachgeschlagen werden]. Zu beachten ist hier die Endianness: was in der Doku als <code>0x1234</code> geschrieben ist, muss hier als <code>3412</code> angegeben werden. Anschließend muss man auf der [https://danielwippermann.github.io/resol-vbus/#/vsf oben genannten Seite] nach dem Command 0x0100 für den entsprechenden Regler suchen. Dazu am besten oben nach 0x0100 filtern und dann mit Strg+F die Quelladresse finden. Klickt man in der Zeile auf <code>Bytes</code> bekommt man die Länge der Nachricht, wobei man 1 addieren muss, da es sich um Offsets handelt. Beim RemaSol 1/2 (bzw. DeDietrich Sol Plus ER 709) ist der größte Offset 39, also 40 Bytes. Mit dem Wissen, dass ein Frame 4 Byte enthält, ergibt sich eine Länge von 10 Frames, was einem Hexadezimalwert von <span class="hb6">0x0A</span> entspricht. Nun muss man nur noch die Prüfsumme berechnen (oder durch Schnüffeln am UART ermitteln) Für die Feldzuordnung lohnt sich ein scharfer Blick und Vergleich der <code>Fields</code>-Seite für die [https://danielwippermann.github.io/resol-vbus/#/vsf/fields/00_0010_4221_10_0100 DeltaSol BS Plus] und dem Beispiel in der [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus dieses Reglers] in der Tasmota-Doku. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. Achtung: Es handelt sich um Version 0.1, auf der sich 3 kleine Fehler befinden, die sich allerdings mit Fädeldraht korrigieren lassen. =Downloads= * [[Datei:Vbusesp_0.2.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:ESP8266]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 86603938e205ced12f0a9f6d18fc61951e7cfda7 1750 1749 2022-02-05T21:45:40Z Chris 2 /* Leiterkarten */ Korrekturanleitung hinzugefügt wikitext text/x-wiki [[Bild:vbusesp_top.jpg|thumb|Aufgebauter Leiterkarte (v0.1)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Wenn Basteln und IoT aufeinandertreffen, kommt man fast nicht an den Mikrocontrollern von Espressif vorbei. Genau aus diesem Grund hatte ich schon länger die Idee, ein Leiterkärtchen mit dem ESP8266 zu machen. Also warum nicht einfach den beliebten VBus ohne großes Strippenziehen ins Netzwerk bringen? =Schaltung= Die Schaltung für den VBus basiert auf der für den [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Raspi (v1.3)]], aufseiten des ESP habe ich mich von den verschiedenen Bastelboards inspirieren lassen und die Möglichkeit vorgesehen, sowohl die kleinen ESP01- als auch die etwas vielseitigeren ESP12-Module einzusetzen. Die Versorgung findet über eine Stiftleiste (bzw. angelötete Drähte) oder über eine Micro-USB-Buchse statt. Diese dient nur der Stromversorgung - mehr zum Programmieren des ESP weiter unten. Bei der Verwendung des ESP12-Moduls stehen zusätzlich zum VBus-Interface noch die GPIOs 12, 13, 14 und 16 sowie der ADC-Eingang und die 3,3V-Versorgung zur Verfügung. Hier kann weitere Peripherie wie Sensoren oder Displays angeschlossen werden. Für den Aufbau gibt es mehrere Varianten, die unten aufgeführt sind. Diese können über die Tabs ausgewählt und müssen beim Besorgen der Bauteile und selbstverständlich beim Zusammenbau kombiniert werden. Die theoretische Maximalbestückung sieht wie folgt aus: <gallery> vbusesp_max_sch_1.png | Schaltplan VBus + Stromversorgung vbusesp_max_sch_2.png | Schaltplan ESP8266 und IO vbusesp_max_assy.png | Bestückungsplan </gallery> =BOM= Möglichkeiten schaffen Komplexität. Wie bei den anderen Plattformen lässt sich der Adapter in verschiedenen Varianten aufbauen, wobei ich (auch wenn es gerade bei dieser anbietet) noch immer empfehle, die Optoisolierte aufzubauen. ==Decoder== Neben Optoisoliert und Direkt gibt es noch die Variante ohne ESP - dank der Stiftleiste rechts oben auf der Leiterkarte lässt sich der VBus-Anteil komplett unabhängig vom ESP-Anteil verwenden. Mit Säge und Fingerspitzengefühl lässt sich die Größe auch noch ein gutes Stück reduzieren. Als ESP8266-Modul kann das ESP01 und ESP12(-F) verwendet werden. Getestet wurde bis jetzt nur das ESP12-F, wobei nichts gegen das 01 sprechen dürfte. <tabs> <tab name="Optoisoliert"> Empfohlene Bestückungsvariante. <gallery> vbusesp_optiso_sch_1.png | Variantenschaltplan VBus vbusesp_optiso_sch_2.png | Variantenschaltplan ESP8266 vbusesp_optiso_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 5 || R9, R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Direkt"> <gallery> vbusesp_direct_sch_1.png | Variantenschaltplan VBus vbusesp_direct_sch_2.png | Variantenschaltplan ESP8266 vbusesp_direct_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 4 || R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 2 || Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Optoisoliert (ohne ESP)"> Wer keinen ESP8266 verwenden aber die Vorzüge der verbesserten Schaltung haben möchte, kann den ESP-Anteil vollständig weglassen. Hierfür wird auf dieser Leiterkarte keine Stromversorgung benötigt, da diese vom jeweilig verwendeten Interface (z. B. SBC, USB-UART-Wandler, ...) bezogen werden kann. <gallery> vbusesp_optisonoesp_sch_1.png | Variantenschaltplan VBus vbusesp_optisonoesp_sch_2.png | Variantenschaltplan Interface vbusesp_optisonoesp_assy.png | Bestückungsplan vbusesp_vbusonly_pinout.png | Anschlussbelegung des UART </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> ==Stromversorgung== Für die Stromversorgung gibt es ebenfalls zwei Möglichkeiten: Entweder mit LDO oder Schaltwandler. Wer auf Nummer sicher gehen will, nimmt die billigere LDO-Variante, da ich noch keine Gelegenheit hatte letztere zu testen. Die etwas höhere Stromaufnahme dürfte wahrscheinlich nicht allzu sehr ins Gewicht fallen. <tabs> <tab name="Linearregler"> Empfohlene Bestückungsvariante. <gallery> vbusesp_vregldo_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregldo_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || REG1117 || SOT223 || NCP 1117 ST33T3G |} </tab> <tab name="Schaltwandler"> <gallery> vbusesp_vregsmps_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregsmps_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C9 || 100n || C0603 || X7R-G0603 100N |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C12 || 10p || C0603 || NPO-G0603 10P |- | 1 || R17 || 15k || R0603 || RND 0603 1 15K |- | 1 || L1 || 15u || 242408FPS || L-242408FPS 15µ |- | 1 || R16 || 47k || R0603 || RND 0603 1 47K |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || D6 || BAT43WS || SOD323-W || BAT 43WS |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || IC2 || MCP16301 || SOT23-6 || MCP 16301T-I/CHY |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || D4 || SS13L || SUBSMA || SS 13L |} </tab> </tabs> =Inbetriebnahme/Benutzung= ==Flashing== Wird ein ESP8266 verwendet, muss natürlich erst einmal die Software auf den Mikrocontroller. Das Problem: Der Softwaredownload findet über den selben UART statt, der auch für das VBus-Interface statt. Nun könnte man mit Multiplexern arbeiten, was im Idealfall nur einmal benutzt werden würde und somit mit Kanonen auf Spatzen geschossen wäre. Aus dem gleichen Grund gibt es keinen USB-UART-Konverter auf dem Board: Braucht nur Platz und kostet. Deshalb wird für das erstmalige Flashen ein USB-UART-Adapter, der RTS/DTR anbietet, benötigt. Dieser sollte idealerweise mit 3,3 V arbeite, wobei der ESP wohl auch 5 V toleriert. Die beiden Transistoren für Reset und Bootloader nach WittyCloud/NodeMCU sind bereits vorhanden. Die 5 V-Stromversorgung muss entweder über den USB-Port oder der Stiftleiste SV2 kommen, die Anschlussbelegung des UART an SV4 ist wie folgt: {| class="wikitable" ! Pin || Signal vom UART-Adapter |- | 1 || DTR |- | 3 || TX |- | 7 || RX |- | 9 || RTS |} <gallery> vbusesp_prog_1.png | Anschlussbelegung für das Programmieren per UART vbusesp_prog_2.jpg | Verwendung des WittyCloud-USB-Wandlers </gallery> Liegt das Trägerboard eines WittyCloud herum, müssen DTR und RTS gefädelt werden. ==Betrieb== Ist die Firmware auf dem Chip und es sollen Daten vom VBus decodiert werden, muss ein Jumper zwischen Pin 3 und 4 an SV4 oder ein Lötpunkt auf SJ1 gesetzt werden: <gallery> vbusesp_txjumper.png | UART-Verbindung zwischen VBus und ESP8266 </gallery> =Firmware= Zugegebenermaßen: ich habe zwar seit Jahren ein paar ESP8266-Module herumliegen, mich aber nie so richtig damit auseinandergesetzt. Aber das macht nichts: [https://tasmota.github.io/docs/ Tasmota] unterstützt verschiedene [https://tasmota.github.io/docs/Smart-Meter-Interface/ Smart Metering]-Anbindungen, für die die Firmware allerdings angepasst selbst kompiliert werden muss. Michael hat sich (mit der Unterstützung aus der Tasmota-Community) daran gemacht und freundlicherweise die nötigen Anpassungen zur Verfügung gestellt: Folgendes muss in der Datei <code>tasmota/user_config_override.h</code> ergänzt werden: <source lang="C"> #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ #ifndef USE_SCRIPT #define USE_SCRIPT #endif #ifndef USE_SML_M #define USE_SML_M #endif #ifdef USE_RULES #undef USE_RULES #endif #ifndef SML_REPLACE_VARS #define SML_REPLACE_VARS #endif #ifndef USE_SML_SCRIPT_CMD #define USE_SML_SCRIPT_CMD #endif #ifndef SML_MAX_VARS #define SML_MAX_VARS 20 #endif #ifndef USE_SCRIPT_JSON_EXPORT #define USE_SCRIPT_JSON_EXPORT #endif #ifndef USE_SCRIPT_WEB_DISPLAY #define USE_SCRIPT_WEB_DISPLAY #endif </source> ==Konfiguration== Nach dem Flashen des Mikrocontrollers, was für fertige Builds auch über den Tasmotizer erfolgen kann, kann unter <code>Main-Menu -> Console -> Edit Script</code> das [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus Script ergänzt] werden. Mit dem Befehl <code>sensor53 d1</code> kann man den Header für die [https://tasmota.github.io/docs/Smart-Meter-Interface/#meter-metrics Meter Metrics] ermitteln und im Script entsprechend anpassen. Für die RemaSol B/2 sieht das wie folgt aus: <source> r="1,aa10005d101000010a67" coltemp=0 Byte1=0 Byte2=0 >S coltemp=sml[1] Byte1=coltemp>>8 Byte2=coltemp&0xff if Byte1==0x00 { coltemp=coltemp&0xff } if Byte1==0xff { coltemp=(coltemp-0x10000) } coltemp=coltemp*0.1 >B =>sensor53 r >M 1 +1,3,v,0,9600,Solar %r%vo0uw@1,KollektorBase,°C,kolbase,2 %r%vo0uw@10,KollektorOrg,°C,kolorg,2 %r%vo2uw@10,Speicher unten,°C,spu,1 %r%vo4uw@10,Speicher oben,°C,spo,1 %r%vo8ub@1,Pumpe,%%,pump,0 # >J ,"Calculated":{"kol":%coltemp%} >W Kollektor berechnet: {m} %coltemp% °C </source> Anmerkung: Hierbei handelt es sich um einen direkten Copy & Paste aus Michaels Script. Je nach Konfiguration der Anlage kann es Abweichungen geben. Um den Fragen zuvorzukommen - die Anpassung auf die Jeweilige Anlage beginnt in der ersten Zeile: <code> r="1,<span class="hb1">aa</span><span class="hb2">1000</span><span class="hb3">5d10</span><span class="hb4">10</span><span class="hb5">0001</span><span class="hb6">0a</span><span class="hb7">67</span>" </code> Die Farben entsprechen dem Beispiel von der [[VBus-Decoder#Protokoll|Artikelhauptseite]], kurzum: * <span class="hb1">aa</span>: Sync-Wort * <span class="hb2">1000</span>: Zieladresse * <span class="hb3">5d10</span>: Quelladresse * <span class="hb4">10</span>: Protokollversion * <span class="hb5">0001</span>: Befehl * <span class="hb6">0a</span>: Anzahl Nutzdatenframes * <span class="hb7">67</span>: Prüfsumme Die <span class="hb3">Quelladresse</span> kann in der [https://danielwippermann.github.io/resol-vbus/#/vsf VBus-Spezifikation nachgeschlagen werden]. Zu beachten ist hier die Endianness: was in der Doku als <code>0x1234</code> geschrieben ist, muss hier als <code>3412</code> angegeben werden. Anschließend muss man auf der [https://danielwippermann.github.io/resol-vbus/#/vsf oben genannten Seite] nach dem Command 0x0100 für den entsprechenden Regler suchen. Dazu am besten oben nach 0x0100 filtern und dann mit Strg+F die Quelladresse finden. Klickt man in der Zeile auf <code>Bytes</code> bekommt man die Länge der Nachricht, wobei man 1 addieren muss, da es sich um Offsets handelt. Beim RemaSol 1/2 (bzw. DeDietrich Sol Plus ER 709) ist der größte Offset 39, also 40 Bytes. Mit dem Wissen, dass ein Frame 4 Byte enthält, ergibt sich eine Länge von 10 Frames, was einem Hexadezimalwert von <span class="hb6">0x0A</span> entspricht. Nun muss man nur noch die Prüfsumme berechnen (oder durch Schnüffeln am UART ermitteln) Für die Feldzuordnung lohnt sich ein scharfer Blick und Vergleich der <code>Fields</code>-Seite für die [https://danielwippermann.github.io/resol-vbus/#/vsf/fields/00_0010_4221_10_0100 DeltaSol BS Plus] und dem Beispiel in der [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus dieses Reglers] in der Tasmota-Doku. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. Achtung: Es handelt sich um Version 0.1, auf der sich 3 kleine Fehler befinden, die sich allerdings mit Fädeldraht korrigieren lassen: ==Hotfix für v0.1== Um die Leiterkarte Version 0.1 korrekt nutzen zu können, sind bis zu 3 Fixes nötig: ===Bootloader-Schaltung=== Die Beschaltung der Transistoren ist teilweise falsch. Um dies zu korrigieren, müssen 3 Leiterbahnen aufgetrennt werden und die Verbindungen mit Fädeldraht neu hergestellt werden. Das Auftrennen kann je nach Geschmack mit einem kleinen Trennschleifer (Vulgo Dremel) oder einem Messer erfolgen. Statt der zwei Drähte zum unteren der beiden Widerstände kann der Widerstand (im 0603-Gehäuse) auch zwischen die beiden Pads am Transistor gelegt werden und damit ein Schnitt und eine Drahtverbindung gespart werden. <gallery> vbusesp_v01fix_transistor_rewire.png | Korrekturanleitung vbusesp_v01fix_transistor_prep1.jpg | mit dem Skalpell entfernt vbusesp_v01fix_transistor_prep2.jpg | mit dem Trennschleifer durchtrennt vbusesp_v01fix_transistor_done.jpg | Durchgeführte Korrektur </gallery> ===Beschaltung GPIO15 am ESP12== Diese Korrektur ist nur relevant, wenn man ein ESP12-Modul einsetzt. Der Mikrocontroller startet nur, wenn GPIO15 über einen Pull-down mit Masse verbunden ist. Dazu sollte ein 10k-Widerstand zwischen diese beiden Pins, wie unten dargestellt, eingebaut werden: <gallery> vbusesp_v01fix_res.jpg | Durchgeführte Korrektur. Widerstand ist zweckvoll! </gallery> ===Pull-up an Q3=== Wird die Tx-Funktionalität verwendet, blockiert der als Pull-down eingesetzte R14 den Bus. Um dies zu berichtigen muss das linke Pad getrennt und mit und mit VBUS_3V3 verbunden werden: <gallery> vbusesp_v01fix_tx_pull.png | Korrekturanleitung </gallery> =Downloads= * [[Datei:Vbusesp_0.2.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:ESP8266]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] cdfca30ed55524b20643c084d64b9ad9f31881fe 1757 1750 2022-02-05T21:47:49Z Chris 2 /* =Beschaltung GPIO15 am ESP12 */ wikitext text/x-wiki [[Bild:vbusesp_top.jpg|thumb|Aufgebauter Leiterkarte (v0.1)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Wenn Basteln und IoT aufeinandertreffen, kommt man fast nicht an den Mikrocontrollern von Espressif vorbei. Genau aus diesem Grund hatte ich schon länger die Idee, ein Leiterkärtchen mit dem ESP8266 zu machen. Also warum nicht einfach den beliebten VBus ohne großes Strippenziehen ins Netzwerk bringen? =Schaltung= Die Schaltung für den VBus basiert auf der für den [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Raspi (v1.3)]], aufseiten des ESP habe ich mich von den verschiedenen Bastelboards inspirieren lassen und die Möglichkeit vorgesehen, sowohl die kleinen ESP01- als auch die etwas vielseitigeren ESP12-Module einzusetzen. Die Versorgung findet über eine Stiftleiste (bzw. angelötete Drähte) oder über eine Micro-USB-Buchse statt. Diese dient nur der Stromversorgung - mehr zum Programmieren des ESP weiter unten. Bei der Verwendung des ESP12-Moduls stehen zusätzlich zum VBus-Interface noch die GPIOs 12, 13, 14 und 16 sowie der ADC-Eingang und die 3,3V-Versorgung zur Verfügung. Hier kann weitere Peripherie wie Sensoren oder Displays angeschlossen werden. Für den Aufbau gibt es mehrere Varianten, die unten aufgeführt sind. Diese können über die Tabs ausgewählt und müssen beim Besorgen der Bauteile und selbstverständlich beim Zusammenbau kombiniert werden. Die theoretische Maximalbestückung sieht wie folgt aus: <gallery> vbusesp_max_sch_1.png | Schaltplan VBus + Stromversorgung vbusesp_max_sch_2.png | Schaltplan ESP8266 und IO vbusesp_max_assy.png | Bestückungsplan </gallery> =BOM= Möglichkeiten schaffen Komplexität. Wie bei den anderen Plattformen lässt sich der Adapter in verschiedenen Varianten aufbauen, wobei ich (auch wenn es gerade bei dieser anbietet) noch immer empfehle, die Optoisolierte aufzubauen. ==Decoder== Neben Optoisoliert und Direkt gibt es noch die Variante ohne ESP - dank der Stiftleiste rechts oben auf der Leiterkarte lässt sich der VBus-Anteil komplett unabhängig vom ESP-Anteil verwenden. Mit Säge und Fingerspitzengefühl lässt sich die Größe auch noch ein gutes Stück reduzieren. Als ESP8266-Modul kann das ESP01 und ESP12(-F) verwendet werden. Getestet wurde bis jetzt nur das ESP12-F, wobei nichts gegen das 01 sprechen dürfte. <tabs> <tab name="Optoisoliert"> Empfohlene Bestückungsvariante. <gallery> vbusesp_optiso_sch_1.png | Variantenschaltplan VBus vbusesp_optiso_sch_2.png | Variantenschaltplan ESP8266 vbusesp_optiso_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 5 || R9, R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Direkt"> <gallery> vbusesp_direct_sch_1.png | Variantenschaltplan VBus vbusesp_direct_sch_2.png | Variantenschaltplan ESP8266 vbusesp_direct_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 4 || R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 2 || Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Optoisoliert (ohne ESP)"> Wer keinen ESP8266 verwenden aber die Vorzüge der verbesserten Schaltung haben möchte, kann den ESP-Anteil vollständig weglassen. Hierfür wird auf dieser Leiterkarte keine Stromversorgung benötigt, da diese vom jeweilig verwendeten Interface (z. B. SBC, USB-UART-Wandler, ...) bezogen werden kann. <gallery> vbusesp_optisonoesp_sch_1.png | Variantenschaltplan VBus vbusesp_optisonoesp_sch_2.png | Variantenschaltplan Interface vbusesp_optisonoesp_assy.png | Bestückungsplan vbusesp_vbusonly_pinout.png | Anschlussbelegung des UART </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> ==Stromversorgung== Für die Stromversorgung gibt es ebenfalls zwei Möglichkeiten: Entweder mit LDO oder Schaltwandler. Wer auf Nummer sicher gehen will, nimmt die billigere LDO-Variante, da ich noch keine Gelegenheit hatte letztere zu testen. Die etwas höhere Stromaufnahme dürfte wahrscheinlich nicht allzu sehr ins Gewicht fallen. <tabs> <tab name="Linearregler"> Empfohlene Bestückungsvariante. <gallery> vbusesp_vregldo_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregldo_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || REG1117 || SOT223 || NCP 1117 ST33T3G |} </tab> <tab name="Schaltwandler"> <gallery> vbusesp_vregsmps_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregsmps_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C9 || 100n || C0603 || X7R-G0603 100N |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C12 || 10p || C0603 || NPO-G0603 10P |- | 1 || R17 || 15k || R0603 || RND 0603 1 15K |- | 1 || L1 || 15u || 242408FPS || L-242408FPS 15µ |- | 1 || R16 || 47k || R0603 || RND 0603 1 47K |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || D6 || BAT43WS || SOD323-W || BAT 43WS |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || IC2 || MCP16301 || SOT23-6 || MCP 16301T-I/CHY |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || D4 || SS13L || SUBSMA || SS 13L |} </tab> </tabs> =Inbetriebnahme/Benutzung= ==Flashing== Wird ein ESP8266 verwendet, muss natürlich erst einmal die Software auf den Mikrocontroller. Das Problem: Der Softwaredownload findet über den selben UART statt, der auch für das VBus-Interface statt. Nun könnte man mit Multiplexern arbeiten, was im Idealfall nur einmal benutzt werden würde und somit mit Kanonen auf Spatzen geschossen wäre. Aus dem gleichen Grund gibt es keinen USB-UART-Konverter auf dem Board: Braucht nur Platz und kostet. Deshalb wird für das erstmalige Flashen ein USB-UART-Adapter, der RTS/DTR anbietet, benötigt. Dieser sollte idealerweise mit 3,3 V arbeite, wobei der ESP wohl auch 5 V toleriert. Die beiden Transistoren für Reset und Bootloader nach WittyCloud/NodeMCU sind bereits vorhanden. Die 5 V-Stromversorgung muss entweder über den USB-Port oder der Stiftleiste SV2 kommen, die Anschlussbelegung des UART an SV4 ist wie folgt: {| class="wikitable" ! Pin || Signal vom UART-Adapter |- | 1 || DTR |- | 3 || TX |- | 7 || RX |- | 9 || RTS |} <gallery> vbusesp_prog_1.png | Anschlussbelegung für das Programmieren per UART vbusesp_prog_2.jpg | Verwendung des WittyCloud-USB-Wandlers </gallery> Liegt das Trägerboard eines WittyCloud herum, müssen DTR und RTS gefädelt werden. ==Betrieb== Ist die Firmware auf dem Chip und es sollen Daten vom VBus decodiert werden, muss ein Jumper zwischen Pin 3 und 4 an SV4 oder ein Lötpunkt auf SJ1 gesetzt werden: <gallery> vbusesp_txjumper.png | UART-Verbindung zwischen VBus und ESP8266 </gallery> =Firmware= Zugegebenermaßen: ich habe zwar seit Jahren ein paar ESP8266-Module herumliegen, mich aber nie so richtig damit auseinandergesetzt. Aber das macht nichts: [https://tasmota.github.io/docs/ Tasmota] unterstützt verschiedene [https://tasmota.github.io/docs/Smart-Meter-Interface/ Smart Metering]-Anbindungen, für die die Firmware allerdings angepasst selbst kompiliert werden muss. Michael hat sich (mit der Unterstützung aus der Tasmota-Community) daran gemacht und freundlicherweise die nötigen Anpassungen zur Verfügung gestellt: Folgendes muss in der Datei <code>tasmota/user_config_override.h</code> ergänzt werden: <source lang="C"> #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ #ifndef USE_SCRIPT #define USE_SCRIPT #endif #ifndef USE_SML_M #define USE_SML_M #endif #ifdef USE_RULES #undef USE_RULES #endif #ifndef SML_REPLACE_VARS #define SML_REPLACE_VARS #endif #ifndef USE_SML_SCRIPT_CMD #define USE_SML_SCRIPT_CMD #endif #ifndef SML_MAX_VARS #define SML_MAX_VARS 20 #endif #ifndef USE_SCRIPT_JSON_EXPORT #define USE_SCRIPT_JSON_EXPORT #endif #ifndef USE_SCRIPT_WEB_DISPLAY #define USE_SCRIPT_WEB_DISPLAY #endif </source> ==Konfiguration== Nach dem Flashen des Mikrocontrollers, was für fertige Builds auch über den Tasmotizer erfolgen kann, kann unter <code>Main-Menu -> Console -> Edit Script</code> das [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus Script ergänzt] werden. Mit dem Befehl <code>sensor53 d1</code> kann man den Header für die [https://tasmota.github.io/docs/Smart-Meter-Interface/#meter-metrics Meter Metrics] ermitteln und im Script entsprechend anpassen. Für die RemaSol B/2 sieht das wie folgt aus: <source> r="1,aa10005d101000010a67" coltemp=0 Byte1=0 Byte2=0 >S coltemp=sml[1] Byte1=coltemp>>8 Byte2=coltemp&0xff if Byte1==0x00 { coltemp=coltemp&0xff } if Byte1==0xff { coltemp=(coltemp-0x10000) } coltemp=coltemp*0.1 >B =>sensor53 r >M 1 +1,3,v,0,9600,Solar %r%vo0uw@1,KollektorBase,°C,kolbase,2 %r%vo0uw@10,KollektorOrg,°C,kolorg,2 %r%vo2uw@10,Speicher unten,°C,spu,1 %r%vo4uw@10,Speicher oben,°C,spo,1 %r%vo8ub@1,Pumpe,%%,pump,0 # >J ,"Calculated":{"kol":%coltemp%} >W Kollektor berechnet: {m} %coltemp% °C </source> Anmerkung: Hierbei handelt es sich um einen direkten Copy & Paste aus Michaels Script. Je nach Konfiguration der Anlage kann es Abweichungen geben. Um den Fragen zuvorzukommen - die Anpassung auf die Jeweilige Anlage beginnt in der ersten Zeile: <code> r="1,<span class="hb1">aa</span><span class="hb2">1000</span><span class="hb3">5d10</span><span class="hb4">10</span><span class="hb5">0001</span><span class="hb6">0a</span><span class="hb7">67</span>" </code> Die Farben entsprechen dem Beispiel von der [[VBus-Decoder#Protokoll|Artikelhauptseite]], kurzum: * <span class="hb1">aa</span>: Sync-Wort * <span class="hb2">1000</span>: Zieladresse * <span class="hb3">5d10</span>: Quelladresse * <span class="hb4">10</span>: Protokollversion * <span class="hb5">0001</span>: Befehl * <span class="hb6">0a</span>: Anzahl Nutzdatenframes * <span class="hb7">67</span>: Prüfsumme Die <span class="hb3">Quelladresse</span> kann in der [https://danielwippermann.github.io/resol-vbus/#/vsf VBus-Spezifikation nachgeschlagen werden]. Zu beachten ist hier die Endianness: was in der Doku als <code>0x1234</code> geschrieben ist, muss hier als <code>3412</code> angegeben werden. Anschließend muss man auf der [https://danielwippermann.github.io/resol-vbus/#/vsf oben genannten Seite] nach dem Command 0x0100 für den entsprechenden Regler suchen. Dazu am besten oben nach 0x0100 filtern und dann mit Strg+F die Quelladresse finden. Klickt man in der Zeile auf <code>Bytes</code> bekommt man die Länge der Nachricht, wobei man 1 addieren muss, da es sich um Offsets handelt. Beim RemaSol 1/2 (bzw. DeDietrich Sol Plus ER 709) ist der größte Offset 39, also 40 Bytes. Mit dem Wissen, dass ein Frame 4 Byte enthält, ergibt sich eine Länge von 10 Frames, was einem Hexadezimalwert von <span class="hb6">0x0A</span> entspricht. Nun muss man nur noch die Prüfsumme berechnen (oder durch Schnüffeln am UART ermitteln) Für die Feldzuordnung lohnt sich ein scharfer Blick und Vergleich der <code>Fields</code>-Seite für die [https://danielwippermann.github.io/resol-vbus/#/vsf/fields/00_0010_4221_10_0100 DeltaSol BS Plus] und dem Beispiel in der [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus dieses Reglers] in der Tasmota-Doku. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. Achtung: Es handelt sich um Version 0.1, auf der sich 3 kleine Fehler befinden, die sich allerdings mit Fädeldraht korrigieren lassen: ==Hotfix für v0.1== Um die Leiterkarte Version 0.1 korrekt nutzen zu können, sind bis zu 3 Fixes nötig: ===Bootloader-Schaltung=== Die Beschaltung der Transistoren ist teilweise falsch. Um dies zu korrigieren, müssen 3 Leiterbahnen aufgetrennt werden und die Verbindungen mit Fädeldraht neu hergestellt werden. Das Auftrennen kann je nach Geschmack mit einem kleinen Trennschleifer (Vulgo Dremel) oder einem Messer erfolgen. Statt der zwei Drähte zum unteren der beiden Widerstände kann der Widerstand (im 0603-Gehäuse) auch zwischen die beiden Pads am Transistor gelegt werden und damit ein Schnitt und eine Drahtverbindung gespart werden. <gallery> vbusesp_v01fix_transistor_rewire.png | Korrekturanleitung vbusesp_v01fix_transistor_prep1.jpg | mit dem Skalpell entfernt vbusesp_v01fix_transistor_prep2.jpg | mit dem Trennschleifer durchtrennt vbusesp_v01fix_transistor_done.jpg | Durchgeführte Korrektur </gallery> ===Beschaltung GPIO15 am ESP12=== Diese Korrektur ist nur relevant, wenn man ein ESP12-Modul einsetzt. Der Mikrocontroller startet nur, wenn GPIO15 über einen Pull-down mit Masse verbunden ist. Dazu sollte ein 10k-Widerstand zwischen diese beiden Pins, wie unten dargestellt, eingebaut werden: <gallery> vbusesp_v01fix_res.jpg | Durchgeführte Korrektur. Widerstand ist zweckvoll! </gallery> ===Pull-up an Q3=== Wird die Tx-Funktionalität verwendet, blockiert der als Pull-down eingesetzte R14 den Bus. Um dies zu berichtigen muss das linke Pad getrennt und mit und mit VBUS_3V3 verbunden werden: <gallery> vbusesp_v01fix_tx_pull.png | Korrekturanleitung </gallery> =Downloads= * [[Datei:Vbusesp_0.2.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:ESP8266]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] a12f706a6e66765b94c335d911a04fd56a7b822a 1763 1757 2022-10-28T19:58:11Z Chris 2 Tippfehler korrigiert, Daten für 0.1 hochgeladen wikitext text/x-wiki [[Bild:vbusesp_top.jpg|thumb|Aufgebauter Leiterkarte (v0.1)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Wenn Basteln und IoT aufeinandertreffen, kommt man fast nicht an den Mikrocontrollern von Espressif vorbei. Genau aus diesem Grund hatte ich schon länger die Idee, ein Leiterkärtchen mit dem ESP8266 zu machen. Also warum nicht einfach den beliebten VBus ohne großes Strippenziehen ins Netzwerk bringen? =Schaltung= Die Schaltung für den VBus basiert auf der für den [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Raspi (v1.3)]], aufseiten des ESP habe ich mich von den verschiedenen Bastelboards inspirieren lassen und die Möglichkeit vorgesehen, sowohl die kleinen ESP01- als auch die etwas vielseitigeren ESP12-Module einzusetzen. Die Versorgung findet über eine Stiftleiste (bzw. angelötete Drähte) oder über eine Micro-USB-Buchse statt. Diese dient nur der Stromversorgung - mehr zum Programmieren des ESP weiter unten. Bei der Verwendung des ESP12-Moduls stehen zusätzlich zum VBus-Interface noch die GPIOs 12, 13, 14 und 16 sowie der ADC-Eingang und die 3,3V-Versorgung zur Verfügung. Hier kann weitere Peripherie wie Sensoren oder Displays angeschlossen werden. Für den Aufbau gibt es mehrere Varianten, die unten aufgeführt sind. Diese können über die Tabs ausgewählt und müssen beim Besorgen der Bauteile und selbstverständlich beim Zusammenbau kombiniert werden. Die theoretische Maximalbestückung sieht wie folgt aus: <gallery> vbusesp_max_sch_1.png | Schaltplan VBus + Stromversorgung vbusesp_max_sch_2.png | Schaltplan ESP8266 und IO vbusesp_max_assy.png | Bestückungsplan </gallery> =BOM= Möglichkeiten schaffen Komplexität. Wie bei den anderen Plattformen lässt sich der Adapter in verschiedenen Varianten aufbauen, wobei ich (auch wenn es gerade bei dieser anbietet) noch immer empfehle, die Optoisolierte aufzubauen. ==Decoder== Neben Optoisoliert und Direkt gibt es noch die Variante ohne ESP - dank der Stiftleiste rechts oben auf der Leiterkarte lässt sich der VBus-Anteil komplett unabhängig vom ESP-Anteil verwenden. Mit Säge und Fingerspitzengefühl lässt sich die Größe auch noch ein gutes Stück reduzieren. Als ESP8266-Modul kann das ESP01 und ESP12(-F) verwendet werden. Getestet wurde bis jetzt nur das ESP12-F, wobei nichts gegen das 01 sprechen dürfte. <tabs> <tab name="Optoisoliert"> Empfohlene Bestückungsvariante. <gallery> vbusesp_optiso_sch_1.png | Variantenschaltplan VBus vbusesp_optiso_sch_2.png | Variantenschaltplan ESP8266 vbusesp_optiso_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 5 || R9, R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Direkt"> <gallery> vbusesp_direct_sch_1.png | Variantenschaltplan VBus vbusesp_direct_sch_2.png | Variantenschaltplan ESP8266 vbusesp_direct_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 4 || R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 2 || Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Optoisoliert (ohne ESP)"> Wer keinen ESP8266 verwenden aber die Vorzüge der verbesserten Schaltung haben möchte, kann den ESP-Anteil vollständig weglassen. Hierfür wird auf dieser Leiterkarte keine Stromversorgung benötigt, da diese vom jeweilig verwendeten Interface (z. B. SBC, USB-UART-Wandler, ...) bezogen werden kann. <gallery> vbusesp_optisonoesp_sch_1.png | Variantenschaltplan VBus vbusesp_optisonoesp_sch_2.png | Variantenschaltplan Interface vbusesp_optisonoesp_assy.png | Bestückungsplan vbusesp_vbusonly_pinout.png | Anschlussbelegung des UART </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> ==Stromversorgung== Für die Stromversorgung gibt es ebenfalls zwei Möglichkeiten: Entweder mit LDO oder Schaltwandler. Wer auf Nummer sicher gehen will, nimmt die billigere LDO-Variante, da ich noch keine Gelegenheit hatte letztere zu testen. Die etwas höhere Stromaufnahme dürfte wahrscheinlich nicht allzu sehr ins Gewicht fallen. <tabs> <tab name="Linearregler"> Empfohlene Bestückungsvariante. <gallery> vbusesp_vregldo_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregldo_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || REG1117 || SOT223 || NCP 1117 ST33T3G |} </tab> <tab name="Schaltwandler"> <gallery> vbusesp_vregsmps_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregsmps_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C9 || 100n || C0603 || X7R-G0603 100N |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C12 || 10p || C0603 || NPO-G0603 10P |- | 1 || R17 || 15k || R0603 || RND 0603 1 15K |- | 1 || L1 || 15u || 242408FPS || L-242408FPS 15µ |- | 1 || R16 || 47k || R0603 || RND 0603 1 47K |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || D6 || BAT43WS || SOD323-W || BAT 43WS |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || IC2 || MCP16301 || SOT23-6 || MCP 16301T-I/CHY |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || D4 || SS13L || SUBSMA || SS 13L |} </tab> </tabs> =Inbetriebnahme/Benutzung= ==Flashing== Wird ein ESP8266 verwendet, muss natürlich erst einmal die Software auf den Mikrocontroller. Das Problem: Der Softwaredownload findet über den selben UART statt, der auch für das VBus-Interface statt. Nun könnte man mit Multiplexern arbeiten, was im Idealfall nur einmal benutzt werden würde und somit mit Kanonen auf Spatzen geschossen wäre. Aus dem gleichen Grund gibt es keinen USB-UART-Konverter auf dem Board: Braucht nur Platz und kostet. Deshalb wird für das erstmalige Flashen ein USB-UART-Adapter, der RTS/DTR anbietet, benötigt. Dieser sollte idealerweise mit 3,3 V arbeite, wobei der ESP wohl auch 5 V toleriert. Die beiden Transistoren für Reset und Bootloader nach WittyCloud/NodeMCU sind bereits vorhanden. Die 5 V-Stromversorgung muss entweder über den USB-Port oder der Stiftleiste SV2 kommen, die Anschlussbelegung des UART an SV4 ist wie folgt: {| class="wikitable" ! Pin || Signal vom UART-Adapter |- | 1 || DTR |- | 3 || TX |- | 7 || RX |- | 9 || RTS |} <gallery> vbusesp_prog_1.png | Anschlussbelegung für das Programmieren per UART vbusesp_prog_2.jpg | Verwendung des WittyCloud-USB-Wandlers </gallery> Liegt das Trägerboard eines WittyCloud herum, müssen DTR und RTS gefädelt werden. ==Betrieb== Ist die Firmware auf dem Chip und es sollen Daten vom VBus decodiert werden, muss ein Jumper zwischen Pin 3 und 4 an SV4 oder ein Lötpunkt auf SJ1 gesetzt werden: <gallery> vbusesp_txjumper.png | UART-Verbindung zwischen VBus und ESP8266 </gallery> =Firmware= Zugegebenermaßen: ich habe zwar seit Jahren ein paar ESP8266-Module herumliegen, mich aber nie so richtig damit auseinandergesetzt. Aber das macht nichts: [https://tasmota.github.io/docs/ Tasmota] unterstützt verschiedene [https://tasmota.github.io/docs/Smart-Meter-Interface/ Smart Metering]-Anbindungen, für die die Firmware allerdings angepasst selbst kompiliert werden muss. Michael hat sich (mit der Unterstützung aus der Tasmota-Community) daran gemacht und freundlicherweise die nötigen Anpassungen zur Verfügung gestellt: Folgendes muss in der Datei <code>tasmota/user_config_override.h</code> ergänzt werden: <source lang="C"> #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ #ifndef USE_SCRIPT #define USE_SCRIPT #endif #ifndef USE_SML_M #define USE_SML_M #endif #ifdef USE_RULES #undef USE_RULES #endif #ifndef SML_REPLACE_VARS #define SML_REPLACE_VARS #endif #ifndef USE_SML_SCRIPT_CMD #define USE_SML_SCRIPT_CMD #endif #ifndef SML_MAX_VARS #define SML_MAX_VARS 20 #endif #ifndef USE_SCRIPT_JSON_EXPORT #define USE_SCRIPT_JSON_EXPORT #endif #ifndef USE_SCRIPT_WEB_DISPLAY #define USE_SCRIPT_WEB_DISPLAY #endif </source> ==Konfiguration== Nach dem Flashen des Mikrocontrollers, was für fertige Builds auch über den Tasmotizer erfolgen kann, kann unter <code>Main-Menu -> Console -> Edit Script</code> das [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus Script ergänzt] werden. Mit dem Befehl <code>sensor53 d1</code> kann man den Header für die [https://tasmota.github.io/docs/Smart-Meter-Interface/#meter-metrics Meter Metrics] ermitteln und im Script entsprechend anpassen. Für die RemaSol B/2 sieht das wie folgt aus: <source> r="1,aa10005d101000010a67" coltemp=0 Byte1=0 Byte2=0 >S coltemp=sml[1] Byte1=coltemp>>8 Byte2=coltemp&0xff if Byte1==0x00 { coltemp=coltemp&0xff } if Byte1==0xff { coltemp=(coltemp-0x10000) } coltemp=coltemp*0.1 >B =>sensor53 r >M 1 +1,3,v,0,9600,Solar %r%vo0uw@1,KollektorBase,°C,kolbase,2 %r%vo0uw@10,KollektorOrg,°C,kolorg,2 %r%vo2uw@10,Speicher unten,°C,spu,1 %r%vo4uw@10,Speicher oben,°C,spo,1 %r%vo8ub@1,Pumpe,%%,pump,0 # >J ,"Calculated":{"kol":%coltemp%} >W Kollektor berechnet: {m} %coltemp% °C </source> Anmerkung: Hierbei handelt es sich um einen direkten Copy & Paste aus Michaels Script. Je nach Konfiguration der Anlage kann es Abweichungen geben. Um den Fragen zuvorzukommen - die Anpassung auf die Jeweilige Anlage beginnt in der ersten Zeile: <code> r="1,<span class="hb1">aa</span><span class="hb2">1000</span><span class="hb3">5d10</span><span class="hb4">10</span><span class="hb5">0001</span><span class="hb6">0a</span><span class="hb7">67</span>" </code> Die Farben entsprechen dem Beispiel von der [[VBus-Decoder#Protokoll|Artikelhauptseite]], kurzum: * <span class="hb1">aa</span>: Sync-Wort * <span class="hb2">1000</span>: Zieladresse * <span class="hb3">5d10</span>: Quelladresse * <span class="hb4">10</span>: Protokollversion * <span class="hb5">0001</span>: Befehl * <span class="hb6">0a</span>: Anzahl Nutzdatenframes * <span class="hb7">67</span>: Prüfsumme Die <span class="hb3">Quelladresse</span> kann in der [https://danielwippermann.github.io/resol-vbus/#/vsf VBus-Spezifikation nachgeschlagen werden]. Zu beachten ist hier die Endianness: was in der Doku als <code>0x1234</code> geschrieben ist, muss hier als <code>3412</code> angegeben werden. Anschließend muss man auf der [https://danielwippermann.github.io/resol-vbus/#/vsf oben genannten Seite] nach dem Command 0x0100 für den entsprechenden Regler suchen. Dazu am besten oben nach 0x0100 filtern und dann mit Strg+F die Quelladresse finden. Klickt man in der Zeile auf <code>Bytes</code> bekommt man die Länge der Nachricht, wobei man 1 addieren muss, da es sich um Offsets handelt. Beim RemaSol 1/2 (bzw. DeDietrich Sol Plus ER 709) ist der größte Offset 39, also 40 Bytes. Mit dem Wissen, dass ein Frame 4 Byte enthält, ergibt sich eine Länge von 10 Frames, was einem Hexadezimalwert von <span class="hb6">0x0A</span> entspricht. Nun muss man nur noch die Prüfsumme berechnen (oder durch Schnüffeln am UART ermitteln) Für die Feldzuordnung lohnt sich ein scharfer Blick und Vergleich der <code>Fields</code>-Seite für die [https://danielwippermann.github.io/resol-vbus/#/vsf/fields/00_0010_4221_10_0100 DeltaSol BS Plus] und dem Beispiel in der [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus dieses Reglers] in der Tasmota-Doku. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. Achtung: Es handelt sich um Version 0.1, auf der sich 3 kleine Fehler befinden, die sich allerdings mit Fädeldraht korrigieren lassen: ==Hotfix für v0.1== Um die Leiterkarte Version 0.1 korrekt nutzen zu können, sind bis zu 3 Fixes nötig: ===Bootloader-Schaltung=== Die Beschaltung der Transistoren ist teilweise falsch. Um dies zu korrigieren, müssen 3 Leiterbahnen aufgetrennt werden und die Verbindungen mit Fädeldraht neu hergestellt werden. Das Auftrennen kann je nach Geschmack mit einem kleinen Trennschleifer (Vulgo Dremel) oder einem Messer erfolgen. Statt der zwei Drähte zum unteren der beiden Widerstände kann der Widerstand (im 0603-Gehäuse) auch zwischen die beiden Pads am Transistor gelegt werden und damit ein Schnitt und eine Drahtverbindung gespart werden. <gallery> vbusesp_v01fix_transistor_rewire.png | Korrekturanleitung vbusesp_v01fix_transistor_prep1.jpg | mit dem Skalpell entfernt vbusesp_v01fix_transistor_prep2.jpg | mit dem Trennschleifer durchtrennt vbusesp_v01fix_transistor_done.jpg | Durchgeführte Korrektur </gallery> ===Beschaltung GPIO15 am ESP12=== Diese Korrektur ist nur relevant, wenn man ein ESP12-Modul einsetzt. Der Mikrocontroller startet nur, wenn GPIO15 über einen Pull-down mit Masse verbunden ist. Dazu sollte ein 10k-Widerstand zwischen diese beiden Pins, wie unten dargestellt, eingebaut werden: <gallery> vbusesp_v01fix_res.jpg | Durchgeführte Korrektur. Widerstand ist zweckvoll! </gallery> ===Pull-up an Q3=== Wird die Tx-Funktionalität verwendet, blockiert der als Pull-down eingesetzte R14 den Bus. Um dies zu berichtigen muss das linke Pad getrennt und mit und mit VBUS_3V3 verbunden werden: <gallery> vbusesp_v01fix_tx_pull.png | Korrekturanleitung </gallery> =Downloads= * [[Datei:Vbusesp_0.2.zip]] EAGLE-Dateien Adapter v0.2 für den ESP8266 ==Archiv== * [[Datei:Vbusesp_0.1.zip]] EAGLE-Dateien Adapter v0.1 für den ESP8266 [[Kategorie:ESP8266]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] d878d8b984c1d73b418825eeff209914f2b21552 Datei:Vbusesp v01fix tx pull.png 6 769 1751 2022-02-05T21:46:13Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp v01fix res.jpg 6 770 1752 2022-02-05T21:46:13Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp v01fix transistor done.jpg 6 771 1753 2022-02-05T21:46:13Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp v01fix transistor rewire.png 6 772 1754 2022-02-05T21:46:13Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp v01fix transistor prep1.jpg 6 773 1755 2022-02-05T21:46:13Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp v01fix transistor prep2.jpg 6 774 1756 2022-02-05T21:46:13Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder 0 120 1758 1724 2022-02-09T20:35:00Z Chris 2 /* Adressen */ Defekten Link korrigiert; vielen Dank an Christian für den Hinweis! wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokolls erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/#/vsf Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Achtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter für den ESP8266|Adapter für den ESP8266]]== Noch etwas kleiner als für den Raspberry Pi: Ein Adapter mit ESP8266-Modulen. <gallery> vbusesp_top.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] Oliver hat basierend auf dem Code von Nicki eine Schnittstelle zur [https://www.volkszaehler.org/ Volkszähler]-Middleware gebaut: <pre> Der Code nutzt die Resol-Decoder-Lib von Nicki, die ist auch mit dabei. In der config.py stellt man die Adresse der Middleware in seinem Netzwerk, sowie die UUID der Kanäle ein, damit man die Daten referenzieren kann. (Zum Test kann man auch simulierte Daten nutzen, oder die Ausgabe in ein File schreiben lassen) </pre> * [[Datei:Vbus_volkszaehler.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 642c2f95e34a07a4fe1936d92831af1a541240f9 1761 1758 2022-10-09T18:29:02Z Chris 2 Typo wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokoll erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Das kann entweder durch das Anleitung erfolgen (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung) oder durch Nachmessen: An den VBus-Klemmen sollte eine (zappelnde) Spannung von etwa 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/#/vsf Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Achtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter für den ESP8266|Adapter für den ESP8266]]== Noch etwas kleiner als für den Raspberry Pi: Ein Adapter mit ESP8266-Modulen. <gallery> vbusesp_top.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] Oliver hat basierend auf dem Code von Nicki eine Schnittstelle zur [https://www.volkszaehler.org/ Volkszähler]-Middleware gebaut: <pre> Der Code nutzt die Resol-Decoder-Lib von Nicki, die ist auch mit dabei. In der config.py stellt man die Adresse der Middleware in seinem Netzwerk, sowie die UUID der Kanäle ein, damit man die Daten referenzieren kann. (Zum Test kann man auch simulierte Daten nutzen, oder die Ausgabe in ein File schreiben lassen) </pre> * [[Datei:Vbus_volkszaehler.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] b2d4fcc6fb19386bd6559bac3046110e0688f7e8 Tchibo Wetterstation 0 299 1759 774 2022-04-12T20:41:39Z Chris 2 Kategorien wikitext text/x-wiki [[Datei:TCM_vorne.jpg|thumb|Tchibo Wetterstation]] Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. <gallery> Datei:TCM_innen.jpg|Verbasteltes Innenleben der Wetterstation Datei:TCM_sender.jpg|Außensensor/Sender </gallery> Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Das Wissen über Kanalkodierung, Codeverkettung und Faltungscodes ist bei den Herstellern von solchem Zeug wohl noch nicht angekommen. Hat immerhin den Vorteil, dass es Leute wie ich nicht zu schwer haben. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? Sicher ist zumindest, dass 36 Bit übertragen werden. ==Datenfarm== Nachdem ich über mehrere Abende hinweg sporadisch Werte aufzeichnete (und erzeugte) bekam ich schließlich knapp 50 Datensätze, die ausgewertet werden wollten. Um Copy & Paste-Orgien in Excel zu ersparen, bastelte ich mir ein kleines PHP-Script, das die Zeitstempel in Binärdaten umwandelt: <source lang="php"> function timing2data($filename) { $fh = fopen($filename, "r"); $lasttime = -1; $data = array(); while($line = fgets($fh)) { $time = explode(", ", $line); $time = floatval($time[0]); if($lasttime !== -1) { $val = round(($time - $lasttime) * 1000); switch($val) { case 9: echo "\n"; break; case 0: echo ""; break; case 2: echo "0"; break; case 4: echo "1"; break; default: echo "<".$val.">"; break; } } $lasttime = $time; } fclose($fh); } </source> Hier habe ich auch die Annahme getroffen, dass ein kurzer Puls 0 und ein langer 1 entspricht (ich sollte richtig liegen). Die Ausgabe sieht dann zum Beispiel wie folgt aus: <pre> 000001010000111001111111100100010000 0000010100001110011111<673><19> </pre> die Werte in den spitzen Klammern sind Pausenzeiten, die nicht als 1, 0 oder Sync erkannt wurden und somit Übertragungsfehler darstellen. Bei der Auswertung fanden sich dann auch einige Datensätze, bei denen die Auswertung nicht mehr allzu zuverlässig war - also gerade so zwei Übereinstimmungen in den Datenworten. Aber es hat gereicht. In Excel ging dann die Suche nach der Antwort los. ==Beispieldaten== {| class="wikitable sortable" |- ! Temperatur !! Luftfeuchtigkeit !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 |- | 24,1°C || 43% || 0000 || 0101 || 0010 || 1000 || 1111 || 0000 || 1100 || 0010 || 0101 |- | 24,6°C || 45% || 0000 || 0101 || 0010 || 0110 || 1111 || 0000 || 1010 || 0010 || 1100 |- | 24,8°C || 49% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 1001 || 0010 || 1111 |- | 24,9°C || 49% || 0000 || 0101 || 0100 || 1001 || 1111 || 0000 || 1001 || 0010 || 0111 |- | 24,7°C || 50% || 0000 || 0101 || 0100 || 1110 || 1111 || 0000 || 0000 || 1010 || 0001 |- | 24,8°C || 50% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 0000 || 1010 || 1110 |- | 24,6°C || 51% || 0000 || 0101 || 0100 || 0110 || 1111 || 0000 || 1000 || 1010 || 0001 |- | 15,7°C || 52% || 0000 || 0101 || 0100 || 1011 || 1001 || 0000 || 0100 || 1010 || 0110 |- | 15,9°C || 52% || 0000 || 0101 || 0100 || 1111 || 1001 || 0000 || 0100 || 1010 || 0010 |- | 16,1°C || 52% || 0000 || 0101 || 0100 || 1000 || 0101 || 0000 || 0100 || 1010 || 1000 |- | 16,3°C || 52% || 0000 || 0101 || 0100 || 1100 || 0101 || 0000 || 0100 || 1010 || 1111 |- | 14,9°C || 53% || 0000 || 0101 || 0100 || 1010 || 1001 || 0000 || 1100 || 1010 || 1011 |- | 15,1°C || 53% || 0000 || 0101 || 0100 || 1110 || 1001 || 0000 || 1100 || 1010 || 1101 |- | 15,5°C || 53% || 0000 || 0101 || 0100 || 1101 || 1001 || 0000 || 1100 || 1010 || 1110 |- | 11,7°C || 62% || 0000 || 0101 || 0100 || 1010 || 1110 || 0000 || 0100 || 0110 || 1111 |- | 11,8°C || 61% || 0000 || 0101 || 0100 || 0110 || 1110 || 0000 || 1000 || 0110 || 1111 |- | 11,9°C || 61% || 0000 || 0101 || 0100 || 1110 || 1110 || 0000 || 1000 || 0110 || 0111 |- | -0,1°C || 89% || 0000 || 0101 || 0000 || 1111 || 1111 || 1111 || 1001 || 0001 || 1110 |- | -0,2°C || 89% || 0000 || 0101 || 0000 || 0111 || 1111 || 1111 || 1001 || 0001 || 0001 |- | -2,5°C || 89% || 0000 || 0101 || 0000 || 1110 || 0111 || 1111 || 1001 || 0001 || 0000 |- |} =="Immer" gleich== "Sie kam aus einem kleineren Ort, wo das Motto galt: 'Wenn du nicht weiter weißt, schlachte ein Schwein'" (na, welcher Film war's?) Wie dem auch sei, zu erst einmal kann man die Bits ausschließen, bei denen nichts passiert. Bei meinen Messungen waren es Nibble 0 und 1. ==Luftfeuchtigkeit== Der Einfachheit halber kommt als erstes die Luftfeuchtigkeit dran. Dazu wurde die Excel-Tabelle nach dieser Spalte sortiert Da in einigen Datensätzen die Luftfeuchtigkeit konstant, die Temperatur jedoch unterschiedlich ist, kann man mit relativ wenig Aufwand die zuständigen Bits ermitteln. Dabei hilft es ungemein, die Bits in Gruppen zu unterteilen. Da sich 36 Bits gut durch 4 teilen lassen, habe ich diese Aufteilung gewählt. Excel-Formeln können beim Auseinanderpflücken der Datenworte enorm helfen (siehe Excel-Sheet). Die entsprechenden Spalten waren schnell gefunden: Nibble 6 und 7. Zum Dekodieren ist es am einfachsten, ähnliche Werte miteinander zu vergleichen. So sieht man z. B. bei den Werten 50% und 51% dass sich bei 51% das höchstwertigste Bit in Nibble 6 ändert. Bei 52% ist nur das zweithöchste Bit aktiv. Ein Muster?! Hilfreich ist hier die Exce-Funktion BININDEZ(), die Binär- in Dezimalwerte umrechnet. Da sich hier aber die höherwertigen Bits "früher" ändern als die niederwertigen ist anzunehmen, dass das Bitmuster verdreht ist. Eine Funktion zum Umkehren von Strings gibt es in Excel anscheinend nicht, allerdings kann man in den Formeln selbstdefinierte Funktionen verwenden. Diese ist in VBA schnell geschrieben: <source lang="VB"> Public Function Reverse(str as String) As String Reverse = StrReverse(str) End Function </source> BININDEZ(Reverse(<Zelle>)) angewendet auf Nibble 6 gibt die Einerstellen aus, Nibble 7 entspricht den Zehnerstellen. Volltreffer! ==Temperatur== Geht man wie bei der Luftfeuchtigkeit vor und sucht Werte mit der kleinstmöglichen Änderung, landet man sehr schnell bei 11,7, 11,8 und 11,9°C. Da Nibble 0, 1, 6 sowie 7 wegfallen, bleiben nur noch Nibble 3. Nibble 8 ist zwar bei 11,8 und 11,9°C unterschiedlich, bei 11,7 und 11,8°C gleich. Wendet man wieder die Excel-Formel von oben an, kommt man in vielen Fällen auf die richtige Nachkommastelle. Für eine vollständige Temperatur ist das natürlich noch nicht genug. Wandelt man Nibble 4 auf die gleiche Weise um, und addiert es um 4 Bit verschoben (bzw. mit 16 multipliziert) mit Nibble 3, hat man einen Temperaturbereich von 25,5°C eingeschlossen. Mit Nibble 5 Wächst der Informationsgehalt auf 12 Bit, also auf 2<sup>12</sup>=4096, was 409,5°C (unter Beachtung von 0°C) entsprechen würde. Das ist natürlich Blödsinn - eher schmilzt der Sensor ;-) Der Grund hierfür ist bei den negativen Temperaturen zu finden (die die Anzahl der Bits nochmals bestätigen), die im [[wpde:Zweierkomplement|Zweierkomplement]] übertragen werden. Dadurch verliert man ein Bit an das Vorzeichen, was immerhin noch Temperaturen von -104,8 bis 204,7°C ermöglichen würde. Der Grund für diesen weiten Anzeigebereich dürfte sein, dass das Rechnen mit 4 Bit einfacher ist, als etwas krummes zu verwenden (aber nur eine Annahme). ==Schalter== Der Sender hat, wie oben im Bild gezeigt, einen Kanalwahlschalter. Dieser Kanal müsste also auch bei der Übertragung mitgesendet werden. Hier ist die Ermittlung denkbar einfach: Umschalten und warten, bis Pakete eintreffen. Diese Information ist in den niederwertigsten zwei Bits (bei Beachtung des "Bitreversals") von Nibble 2. Etwas verwirrend ist hierbei, dass die Bits widerum vertauscht sind. ==Synchronisierung== Beim Herumspielen ist mir aufgefallen, dass das manuelle Synchronisieren von Sender und Empfänger zu einem Piepsen der Wetterstation führt. Also muss dies auch übertragen werden. Gleiches wie bei der Schalterstellung: Daten einfangen und vergleichen. Die Information steckt im 3. Bit von Nibble 2 (ebenfalls nach Bitreversal). ==Low Battery== Wenn man schräg auf das Display der Wetterstation schaut, sieht man ein Low-Battery-Symbol neben der Anzeige der Außentemperatur. Auch diesen Zustand kann man sehr einfach erreichen, indem man die Batterien durch ein Labornetzteil ersetzt. Nach Herunterdrehen des Potis erschien tatsächlich das Symbol im Display. Der Logic Analyzer sagt: Nibble 3, niederwertigstes Bit (muss ich Bitreversal noch erwähnen?). ==Rest== Damit wären eigentlich alle nötigen Informationen entschlüsselt. Es bleiben "nur noch" 12 Bit übrig. Wegen der Anordnung vermute ich hinter dem letzten Nibble eine Prüfsumme. Da sich das erste Nibble nur nach Batteriewechsel änderte, gehe ich davon aus, dass es sich um eine Zufällige Bitfolge zur Erweiterung des Addressraum handelt. Die restlichen 4 Bit sind mir bis dato noch gänzlich unbekannt. ==Prüfsumme== Ich mag sie (zumindest bei Reverse Engineering) einfach nicht. Hauptgrund ist, dass es schlichtweg beliebig viele Verfahren gibt, diese zu berechnen. Egal ob CRC, XOR oder eine einfache Summe wie beim [[ECL-Bus-Decoder]] - es ist einfach undankbar, diese zu rekonstruieren. Aber genug gejammert, Sicherheit kostet nunmal Aufwand. Am Anfang habe ich noch per Bruteforce versucht, die Prüfsumme zu ermitteln, indem ich einfach alle Werte ver-CRC-t, mit XOR verprügelt und addiert habe. Das führte nicht unbedingt zum erwünschten Erfolg - wobei ich dazu sagen muss, dass ich dort auch noch mit der Datenfolge in Reinform (also ohne das umdrehen der 4-Bit-Gruppen) gearbeitet habe. Im zweiten Versuch ging ich wieder über Excel (diese Programm wird man einfach nicht los) - dieses mal mit umgedrehten 4er-Gruppen. Dieses Mal war auch der Ansatz etwas anders: ich suchte mir die Datenpakete mit dem geringsten [[wpde:Hammingabstand|Hammingabstand]] - also jene Datenpakete, die möglichst wenige unterschiedliche Bits haben - heraus, was mehr Erfolg versprach. In der Excel-Datei (Name) habe ich meine "Forschungsergebnisse" zusammengefasst. Es handelt sich tatsächlich nur um eine Quersumme der Nibbles 0 bis 7, die im Modulo 16 mit Nibble 8 ver-XOR-t werden. Kommt 15 heraus, ist alles ok, bei jedem anderen Wert hat das Paket was abbekommen. Mit vorletztem Satz ist der Pseudo-Code <pre> summe := Summe(nibble[0 .. 7]) Binär_AND 0x0F WENN (summe Binär_XOR nibble[8]) = 0x0F DANN "Paket ok" ANDERNFALLS "Paket nicht ok" ENDE WENN </pre> gemeint, falls das besser verständlich ist. ==Zusammenfassung== {| class="wikitable" | '''Nibbles''' | colspan="4" align="center" | Nibble 0 | colspan="4" align="center" | Nibble 1 | colspan="4" align="center" | Nibble 2 | colspan="4" align="center" | Nibble 3 | colspan="4" align="center" | Nibble 4 | colspan="4" align="center" | Nibble 5 | colspan="4" align="center" | Nibble 6 | colspan="4" align="center" | Nibble 7 | colspan="4" align="center" | Nibble 8 |- | '''Empfangen''' | 0 || 0 || 0 || 0 || 0 || 1 || 0 || 1 || 0 || 1 || 0 || 0 || 1 || 1 || 0 || 0 || 1 || 1 || 1 || 1 || 0 || 0 || 0 || 0 || 0 || 0 || 1 || 0 || 1 || 0 || 1 || 0 || 0 || 0 || 0 || 1 |- | '''Bit-Reversal''' | 0 || 0 || 0 || 0 || 1 || 0 || 1 || 0 || 0 || 0 || 1 || 0 || 0 || 0 || 1 || 1 || 1 || 1 || 1 || 1 || 0 || 0 || 0 || 0 || 0 || 1 || 0 || 0 || 0 || 1 || 0 || 1 || 1 || 0 || 0 || 0 |- | '''Bezeichnung''' | colspan="4" align="center" | Adresse | ? | Sync | colspan="2" align="center" | Schalter | ? | ? | ? | Low Bat | colspan="4" align="center" | Temp 0 | colspan="4" align="center" | Temp 1 | colspan="4" align="center" | Temp 2 | colspan="4" align="center" | Hygro 0 | colspan="4" align="center" | Hygro 1 | colspan="4" align="center" | Prüfsumme |- | '''Bedeutung''' | colspan="4" align="center" | 0 | ? | nein | colspan="2" align="center" | 1 | ? | ? | ? | nein | colspan="4" align="center" | 3 | colspan="4" align="center" | 15 | colspan="4" align="center" | 0 | colspan="4" align="center" | 4 | colspan="4" align="center" | 5 | colspan="4" align="center" | 8 |} Die Temperatur lässt sich mit (3 + 15 * 16 + 0 * 256)/10 = 24,3 berechnen. Die Luftfeuchte entspricht 54% Die Prüfsumme hier ist 8, also müssen die restlichen Bytes 7 entsprechen: (0 + 10 + 2 + 3 + 15 + 0 + 4 + 5) AND 15 = 39 AND 15 = 7 7 XOR 8 = 15 => korrekt. =Software= Um weder Logic-Analyzer noch PC für die Erfassung der Außentemperatur und Luftfeuchte zu bemühen, soll der Code wieder auf einen Mikrocontroller. Aus gewohnheit kommt wieder ein AVR ATmega8 zum Einsatz. Zur bequemen Auswertung habe ich dieses mal den ICP (Input Compare Pin) bemüht. Da ich bis jetzt keine größere Erfahrung mit dem Komparator hatte, inspirierte ich mich ein wenig an der Atmel AppNote [http://www.atmel.com/Images/doc8014.pdf AVR135]. Diese beschreibt die Auswertung des Duty-Cylces eines PWM-Signals, also genau das, was man für den Empfänger braucht.= Um einen ungefähren Ausgangswert zu haben, eine kleine Rechnung: das kürzeste Signal hat eine Pulsweite von etwa 2ms, das längste 9ms. Diese müssen also zuverlässig erkannt werden. Der AVR läuft mit 12MHz (der Quarz steckt noch vom [[EMR7370]] im Breadboard), wodurch der AVR eine Zyklusdauer von 83,33ns entspricht. 8ms enstprechen genau 96000 Taktzyklen - etwas viel für den 16-Bit-Timer. Mit dem großzügigen Vorteiler 1024 kommt man auf knapp 94. Bleib noch die Frage, ob die 2 und 4ms sauber unterschieden werden können. 2ms entspricht 23 Timerzyklen, 4ms 47 - also durchaus brauchbare Werte. Zur Bestätigung dieser Theorie baute ich die AppNote so um, dass sie mir die Zählerstände für die jeweiligen High-Zyklen ausgab - mit durchschlagendem Erfolg. Zwar wackelten die Werte ein wenig, das aber im mehr als vertretbaren Rahmen. Zur Auswertung wird eine kleine Statemachine verwendet, was sich schlimmer anhört, als es eigentlich ist. In einer Variable wird der Zustand des Empfangs geschrieben: Warten auf Paket, Synchronisiert + Datenempfang, Fertig. Wird ein Paket empfangen, werden die Bits in ein Array geschrieben und ein Zähler hochgezählt. Ist dieser bei 36 (der Anzahl der Bits) angelangt, geht der Empfänger in den Zustand Fertig über und keine weiteren Bits werden eingelesen. Ist die Auswertung abgeschlossen, geht der Zustand in "Warten" zurück. Wird eine Pulslänge empfangen, die weder einer 1, 0 noch Sync entspricht, wird der Automat ebenfalls in Warten zurückgesetzt, wodurch die zuletzt empfangenen Bits verworfen werden. ==Der Trick mit den Bits== Zunächst habe ich Bits einfach wie sie gekommen sind in den Array geschrieben und erst zur Auswertung in die richtige Reihenfolge gebracht. Das kostet Zeit und Speicher, was sich durch geschickten Code minimieren lässt. Schaut man sich das Nibble-weise Bitreversal genauer an, {| class="wikitable" |- ! Bit mit Nr. !! (Binär) !! soll in Spalte !! (Binär) |- | 0 || 0000 || 4 || 0100 |- | 1 || 0001 || 5 || 0101 |- | 2 || 0010 || 6 || 0110 |- | 3 || 0011 || 7 || 0111 |- | 4 || 0100 || 0 || 0000 |- | 5 || 0101 || 1 || 0001 |- | 6 || 0110 || 2 || 0010 |- | 7 || 0111 || 3 || 0011 |} sieht man, dass man für die Zuordnung eigentlich nur Bit 3 kippen muss. Alle Bits ab Bit 4 kann man für die Zuordnung der Bytes verwenden, was im Quellcode wie folgt aussieht: <source lang="c"> if(bit == TCM_BIT_1) { uint8_t bytepos = tcm_pos >> 3; uint8_t bitpos = (tcm_pos ^ 4) & 7; tcm_bits[bytepos] |= 1<<bitpos; } </source> Das spart wenn ich mich recht erinnere knapp 40 Byte und wahrscheinlich einige Zyklen in der CPU. [[Kategorie:Reverse Engineering]] [[Kategorie:Wetterstation]] 232d7b84b27495ac99397a798ff4930c0a0abb94 Datei:Vbusesp 0.1.zip 6 775 1762 2022-10-28T19:57:15Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol DL2 top.jpg 6 776 1764 2022-11-02T21:22:46Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol DL2 bot.jpg 6 777 1765 2022-11-02T21:22:46Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Deltasol es left.jpg 6 778 1766 2022-11-02T21:24:12Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Deltasol es right.jpg 6 779 1767 2022-11-02T21:24:13Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Deltasol es total.jpg 6 780 1768 2022-11-02T21:24:13Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Deltasol es front.jpg 6 781 1769 2022-11-02T21:24:13Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Resol - Zerlegt 0 782 1770 2022-11-02T21:24:50Z Chris 2 Seite erstellt wikitext text/x-wiki Auf die inneren Werte kommt es an. Damit nicht jeder sein Equipment auseinanderschrauben muss, hier eine Sammlung verschiedener Geräte aus dem Hause Resol: =DeltaSol ES (71002246)= Der DeltaSol ES ist ein Regler mit 36 vorprogrammierten Solar- und Heizanlagen. Vielen Dank an Erhard für die Aufnahmen! <gallery> Deltasol_es_front.jpg | Regler von vorne Deltasol_es_left.jpg | Ansicht von innen links Deltasol_es_total.jpg | Ansicht von innen Deltasol_es_right.jpg | Ansicht von innen rechts </gallery> Hauptkomponenten: * Eingänge Temperatursensoren ** SRDA3.3-4: Low Capacitance TVS Array ** TI HC4051: Analog Mux ** TI LM324: Op-Amp ** TI HC04: Hex Inverter * RS232-Interface ** Intersil 3232ECBZ: RS232-Transceiver * Schaltkontakte ** Finder 34.51.7.012.0010: Printrelais 12VDC Spule, 400VAC 6A/1500VA Kontakt ** Relais Beschriftung nicht lesbar ** Omron G3MB-202P: Halbleiterrelais 5VDC Eingang, 240VAC 2A Last ** TI ULN2???: Treiber für Relais ** TI MC???: Vermutlich Latch/Schieberegister/IO-Expander * Stromversorgung ** MS 5233: 12,5V, 0,4A Transformator ** Spannungsregler Beschriftung nicht lesbar * Brains ** Mikrocontroller Beschriftung nicht lesbar ** RTC Beschriftung nicht lesbar ** Holtek HT1621B: LCD Treiber 32x4 =DL2 (71007402)= Der DL2 ist ein Datenlogger, der neben dem Loggen auf eine SD-Karte auch eine Schnittstelle ins Netzwerk (Ethernet) bereitstellt. Vielen Dank an Erhard für die Aufnahmen! <gallery> Resol_DL2_top.jpg | Oberseite Resol_DL2_bot.jpg | Unterseite </gallery> Hauptkomponenten: * Atmel AT91SAM9260: ARM Mikrocontroller, 180 MHz * Atmel ???: Vermutlich NOR-Flash * Samsung K9F2G08U0B: 256Mbit + 8 MBit NAND Flash * Micron MT48LC16M16A2: 256 Mbit SDRAM * Davicom DM9161: 100BASE-TX Phy [[Kategorie:Solaranlage]] [[Kategorie:VBus]] f0565bac2546dc8abf82fb5abfb9c79452d2d625 Datei:71005014i top m 3v3.png 6 783 1771 2022-11-02T21:53:01Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:71005014i bot.png 6 784 1772 2022-11-02T21:53:01Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:71005014i top.png 6 785 1773 2022-11-02T21:53:01Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014 brd.png 6 786 1774 2022-11-02T21:53:01Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014 M 5V sch.png 6 787 1775 2022-11-02T21:53:01Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:71005014i M 3V3 sch.png 6 788 1776 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014 S 3V3 sch.png 6 789 1777 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:71005014i sch.png 6 790 1778 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:71005014i M 5V sch.png 6 791 1779 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014 sch.png 6 792 1780 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014.zip 6 793 1781 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014 pcb ebay bot.jpg 6 794 1782 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:71005014i S 3V3 sch.png 6 795 1783 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014 pcb regler bot.jpg 6 796 1784 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014 pcb regler top.jpg 6 797 1785 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014 pcb ebay top.jpg 6 798 1786 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014 pcb regler top all layers.jpg 6 799 1787 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014 pcb ebay top refdes.jpg 6 800 1788 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Resol 71005014 pcb ebay top desoldered.jpg 6 801 1789 2022-11-02T21:53:02Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Resol 71005014 Schnittstellenadapter 0 802 1790 2022-11-02T21:55:12Z Chris 2 Seite erstellt wikitext text/x-wiki *Resol 71005014 Schnittstellenadapter =Reparatur= Ab und zu geht auch was kaputt. So schrieb mich vor einiger Zeit Erhard an, der an seinem DeltaSol ES einen Resol DL2 Datenlogger betreibt. Obwohl beide Geräte für sich funktionieren, kamen keine Daten mehr an. An der VBus-Schnittstelle lag ohne Datenlogger nur ein eine Spannung von etwa 4 V an, mit Datenlogger brach die Spannung weiter auf ca. 2,7 V ein. Bei erwarteten ca. 8 Volt und den definierten Schwellen in der [[Datei:VBus-Protokollspezifikation.pdf|Protokollspezifikation]] ist die Begründung für die Funktionslosigkeit gefunden - aber nicht die Ursache. Nach kurzer Recherche bin ich auf einen Thread bei [https://community.home-assistant.io/t/resol-vbus/5304/25 Home Assistant] gestoßen, in dem ein u. a. VBus-Modul gezeigt wird. Rechts oben prankt die Bezeichnung 71005014. In einem Katalog über Resol-Produkte ließ sich zumindest ansatzweise erkennen, dass das Modul auch in anderen Reglern verwendet wird, also ging die Suche nach Ersatz los - und tatsächlich ließ sich das Modul für schlappe 12 Euro auf eBay finden. Es ging ein bisschen Zeit ins Land, bis eine weitere Anfrage bzgl. defektem VBus-Interface kam. Also den Mailthread herausgekramt und nochmal nachgefragt, wie die Reparatur ausging - leider noch nicht ganz so erfolgreich, da das Modul nicht passt. Statt der geraden Stiftleiste ist eine gewinkelte nötig und die Bestückung weicht ab. Also einfach mal gefragt, ob Erhard das Defekte Modul und den Ersatz schicken möchte - und ein paar Tage später lagen die Boards auf dem Tisch: <gallery> Resol 71005014 pcb ebay top.jpg | Oberseite der Leiterkarte von eBay Resol 71005014 pcb ebay bot.jpg | Unterseite der Leiterkarte von eBay Resol 71005014 pcb regler top.jpg | Oberseite der Leiterkarte vom Regler Resol 71005014 pcb regler bot.jpg | Unterseite der Leiterkarte vom Regler </gallery> Abgesehen von der leicht unterschiedlichen Farbe des Lötstopps (und des Weißabgleichs) sieht man der Leiterkarte aus dem Regler deutlich an, dass sie Temperatur im Bereich des Chips links unten gesehen hat. Beim dem Bauteil handelt es sich um einen LM317 - also ein Spannungsregler. ein kurzer Blick ins Datenblatt verrät, dass links unten der Adjust-Pin ist, der Pin links oben der Eingang und die Pins dazwischen die Ausgänge sind. Da die Regler üblicherweise einen Spannungsteiler und damit 2 Widerstände zum Einstellen der Spannung brauchen, wird der Regler wohl anders verwendet wird: Der 24,3 Ohm-Widerstand befindet sich zwischen Ausgang und Adjust, mehr sieht man leider nicht. In diesem Sinne "glücklicherweise" ist der LM317 bei Ersatzleiterkarte der Käfer nicht bestückt - die Leiterbahnen zeigen: die Ausgangspins sind zwar miteinander verbunden, aber das war's auch schon. Ein Via führt lediglich zum Adjust-Pin. Etwas weiter unten im [https://www.ti.com/lit/ds/symlink/lm317l-n.pdf#page=14 Datenblatt] ist auch diese Anwendung aufgeführt: Stromquelle. Deren Stärke lässt sich sehr einfach nach <math>I_\textrm{out} = \frac{1.2}{R}</math> berechnen. Mit 24,3 Ohm ergibt das (Trommelwirbel) 49,4 mA. Die Pins zurückverfolgt wird an den rechten beiden 9 V eingespeist und geschaut, welcher Strom vom Ausgang der Stromquelle nach Masse fließt - unspektakuläre 1,2 mA. Ein LM317 liegt noch herum, also runter das olle Teil und rauf mit dem Neuen. Nochmals nachgemessen: um die 50 mA. Super! Fall erledigt, eintüten und ab dafür! =Reverse Engineering= Äh, nein. So läuft das hier nicht. Aufmerksame Leser werden schon bemerkt haben, dass die Bilder oben (nicht ganz) zufällig die gleiche Größe haben und sehr gleichartig abgebildet sind. Es gibt noch ein weiteres Foto und eine bearbeitete Version - beim Foto fehlen ein paar Bauteile, bei der Bearbeitung haben alle Komponenten einen Namen bekommen und eine Innenbeschaltung hat es auf das Foto geschafft: <gallery> resol 71005014 pcb ebay top desoldered.jpg | Bauteile entfernt resol 71005014 pcb ebay top refdes.jpg | Mit Namen und Innenbeschaltung resol 71005014 pcb regler top all layers.jpg | Alle Lagen überlagert </gallery> Warum Namen? Zugegebenermaßen mag das bei der Komplexität der Schaltung etwas übertrieben sein, aber es hilft, den Schaltplan zu entflechten und im Anschluss beim Placement. Auf eine weitere Lage in naint.net werden Vias markiert, für die wenigen Leiterbahnen auf der Unterseite gibt es ebenfalls eine. ==Bauteile== D3 ist eine mit an Sicherheit grenzender Wahrscheinlichkeit eine TVS-Diode. Nach etwas längerer [https://rtellason.com/semiconductorlogos.html Suche nach dem Logo] stellte sich heraus, dass es sich um ein Teil von General Semiconductor (heute Vishay) handelt. Die Suche nach "KM 66A" brachte zumindest bei Google erst einmal nur eine öffentliche Toilette in Österreich (wen es interessiert: A12 Intall Autobahn, bei km 66,28 Richtung Zams). Hm, das war wohl ein... [https://www.youtube.com/results?search_query=csi+sunglass+moment ...griff ins Klo]?! Unstrittig ist jedenfalls, dass es sich um ein SMB-Gehäuse handelt. Nach etwas mehr Sucherei und dem Auffinden einer alten Version eines Dokuments zum [http://matthieu.benoit.free.fr/cross/competitive/general_semi/marking.pdf PDD Marking] müsste es sich um eine [https://www.vishay.com/docs/88392/smbj.pdf SMBJ7.0A] handeln. Auch wenn mir Parameter wie Breakdown Voltage und Stand-off Voltage etwas niedrig vorkommen - die Angabe deckt sich mit dem vorgeschlagenen Bauteil in der [[Datei:VBus-Protokollspezifikation.pdf|Protokollspezifikation]] D5, die Diode im MiniMelf-Gehäuse, musste kurz die Leiterkarte verlassen um gemessen zu werden, ähnlich wie die Kondensatoren. Bei der Diode handelt es sich mutmaßlich um eine Z-Diode mit 4,7 V Rückwärtsspannung. Widerstände im 0805 Gehäuse haben dankenswerterweise noch Beschriftungen, hier ist einzig R9 etwas tricky: Ist das nun 1091 oder 1601? Ersteres würde 1,09 kOhm bedeuten, letzteres 1,6 kOhm. Da 1,09 in den [[wpde:E-Reihe|E-Reihen]] nicht existiert, muss es wohl 1,6 kOhm sein. Ein anderer Hinweis ist natürlich, dass die 9 rechts unten abgeschrägt ist (ähnlich wie die 2). Eine kleine Gemeinheit: R9 und R11 sind auf den beiden Boards unterschiedlich - eine Erklärung hierzu findet sich weiter unten. T1 dient vermutlich zum Senden der Daten, indem er die VBus-Leitung nach Masse kurschließt. Hätte es mir im Master etwas eleganter vorgestellt, aber warum auch nicht - es funktioniert. Wobei der FET, ein Fairchild RFD14N05L, mit seinen 14 A natürlich durchaus wohlwollend dimensioniert ist. Bei IC2 handelt es sich um einen Komparator, genau genommen einem TI TLC3702; IC3 ist ein Quad 2 Input NAND Gatter mit Schmitt-Trigger-Eingängen. Noch einmal in die Protokollspezifikation gespickt: da wurde das Rad auf keinen Fall neu erfunden. Da muss man beim Reverse Engineering eigentlich nicht viel können und auch kein schlechtes Gewissen haben. Einzig unklar sind die beiden unbestückten Bauteile links oberhalb von IC1. Den Footprints nach zu urteilen dürfte "?1" entweder ein Widerstand oder ein Kondensator sein, "?2" wäre in Hinblick auf D5 ebenfalls eine Diode im MiniMelf-Package. Mehr dazu weiter unten. ==Schaltplan== Den Schaltplan abzuzeichnen in etwa so schnell wie den Artikel bis hier zu schreiben. Auch wenn die Schaltung sehr nah am Referenzschaltplan ist, kleine Unterschiede gibt es doch: D5 ist dort eine gewöhnliche Kleinsignaldiode, die Überspannung nach Vcc ableitet, auf dem Modul ist es mit einer Z-Diode, die nach Masse "verbrennt" etwas besser gelöst. Um es kurz zu machen, so schaut's aus: <gallery> resol_71005014_sch.png | Schaltplan der Basisvariante resol_71005014_M_5V_sch.png | Variante für 5V-Master resol_71005014_S_3V3_sch.png | Variante für 3,3V-Slaves resol_71005014_brd.png | Layout der Basisvariante </gallery> Erhard war so freundlich und hat noch weitere Fotos vom Innenleben des Reglers geschickt (siehe [[link]]) und noch ein paar Messungen durchgeführt. So liegen an dem mit 12V bezeichneten Pin 8 von X1 stolze 20,7 V an. Plausibel? Laut Bild hat die DeltaSol ES ein Transformator mit 12,5 V am Ausgang. Das ergibt einen Spitzenwert von 17,7 V - ohne Berücksichtigung des Gleichrichters und natürlich der etwas höheren Leerlaufspannung. Also ja, plausibel. Die andere Versorgung sowie die IO-Spannung beläuft sich auf 3,3 V. ==Kleine Sünden== Nun wird auch in Hinblick auf die TVS-Diode ein Schuh draus: Die Stromquelle begrenzt, wie oben bereits berechnet, auf etwa 50 mA auf dem Bus. Der Spannungsabfall über diesen dürfte auf jeden Fall unter 2 V liegen. Dementsprechend müsste man auf dem Bus um die 18 V sehen - was aber nicht der Fall ist. Die TVS-Diode ist im Breaktdown und wandelt die Spannungsdifferenz in Wärme um. Da haben wir unsere ca. 8,2 V. Hurra. Nicht. In der Schaltung fließen auf jeden Fall 50 mA, bei den 8,2 V ist das eine Leistung von rechnerisch 410 mW. Der Rest bleibt am LM317 (und seinem Serienwiderstand) hängen, also (20,7 - 8,2 V) * 50 mA = 625 mW. Etwas mehr als 1 Watt für die unbenutzte Kommunikationssschnittstelle, wenn der Regler im Idle ist? Hui. Ok, sobald die Relais anziehen sinkt die Spannung und damit Verlustleistung ein bisschen, aber erstrebenswert ist das nicht. Wird, bei Kommunikation, VBUS nach Masse gezogen, bleibt fast die volle Leistung am armen LM317 hängen - zwar nur kurzzeitigig aber Stress ist Stress. Das erklärt nun auch die Verfärbung der Leiterkarte und ggf. das verfrühte Ableben des ICs. Was macht das eine Watt aus? Bei 24/7-Betrieb im Jahr ca. 8,8 kWh, bei 40 ct/kWh sind das knapp 3,5 Euro. Nicht viel aber nicht nichts, plus leidende Elektronik. Wie man es besser machen kann? Verschiedene Ansätze sind möglich: * Auf der Main-PCB 12 V geregelt bereitstellen oder Spannung verringern - verringert auch die Stromaufnahme der anderen 12V-Komponenten (Relais), die der Schnittstelle aber nur um ein knappes halbes Watt * Zweiter Regler für die Schnittstelle: Spannung auf 8,nochwas Volt regeln und den Strom auf 50 mA begrenzen. So wird die TVS-Diode nicht leitend und wenn nicht kommuniziert wird, wird auch kein Strom sinnlos verbraten. * Breakdown-Voltage der TVS-Diode erhöhen. Höhere Spannung am Bus (und damit Specbruch) * Vorige Punkte in Kombination Sollte jemand tatsächlich so verrückt sein und ein alternatives Modul entwickeln, scheiden Änderungen an der Main-PCB natürlich aus, also bleiben die letzten 3 Punkte. ==Die Widerstände== Wie bereits erwähnt, weichen die Widerstände R9 und R11 auf den beiden Boards etwas ab: {| class="wikitable" ! Variante || R9 || R11 || unterer Knoten || oberer Knoten |- | Regler || 2,4k || 1,4k || 60,0 % || 61,1 % |- | Ersatz || 1,6k || 820R || 61,0 % || 68,7 % |} Multipliziert man die Verhältnisse mit 3,3 und 5 V, findet man bekannte Werte: Bei der Leiterkarte aus dem Regler und 5 V ergeben sich 3,00 und 3,25 V, was den Schaltschwellen für einen Master ergibt, für die Ersatzleiterkarte und einer Spannung von 3,3 V kommen 2,27 und 2,02 V heraus, was noch immer recht gut zu den Werten eines Slaves passt. Nur passt nichts so richtig zu dem tatsächlichen Einsatz - allerdings kann man hier die Kirche im Dorf lassen: Es geht lediglich darum, High und Low möglichst ohne Gezappel zu unterscheiden. Auf ein paar hundert Millivolt kommt es bei den Schaltschwellen sicher nicht an. Überspitzt gesagt könnte man den ganzen Bohei mit Komparator und Optokoppler durch einen Spannungsteiler mit Tiefpass ersetzen. Dürfte in den allermeisten Fällen genauso gut funktionieren. =Verbesserte Version= '''Ungetestet''' Die Unzulänglichkeit des unnötig hohen Stromverbrauches der Originalversion ist Grund genug, das Design anzufassen. Statt den Strom zu begrenzen und die zu hohe Spannung in der TVS-Diode zu verbraten, läuft der LM317 nun als Spannungsregler mit etwa 8,2 V Ausgangsspannung. Der Strom wird über zwei parallele 330 Ohm-Widerstände auf knapp 50 mA begrenzt. Die TVS-Diode hat nun eine Breakdown-Spannung von 10 V - die restlichen Bauteile sind dadurch weiterhin gegen Überspannung geschützt und die "Gefahr", dass sinnlos Leistung verbraten wird, vom Tisch. Die Logik-Gatter werden durch die bekannte und erprobte Beschaltung der Komparatoren ersetzt. Zusätzlich hat die (optionale) Z-Diode ihren Weg in den Schaltplan gefunden. Zum Invertieren von UART_TX wird ein BSS138 eingesetzt, der einen etwas einfacher erhältlichen IRF7470 treibt. Dieser kann zwar deutlich weniger Strom als der ursprüngliche treiben, muss er aber auch nicht. Schlussendlich ist die Leiterkarte auch etwas geschrumpt: <gallery> 71005014i_sch.png | Schaltplan Basisvariante 71005014i_M_3V3_sch.png | Schaltplan 3,3 V Master 71005014i_M_5V_sch.png | Schaltplan 5,0 V Master 71005014i_S_3V3_sch.png | Schaltplan 3,3 V Slave </gallery> <gallery> 71005014i_top.png | Bestückungsplan Oberseite 71005014i_top_m_3v3.png | Bestückungsplan Oberseite 3,3 V Master 71005014i_bot.png | Unterseite Layout </gallery> Die BOM umfasst hier lediglich die (wohl interessanteste) Variante für den 3,3 V Master. Bitte beachten, dass die in EAGLE generierbare BOM nur die Bestellcodes für diese Variante enthalten. {| class="wikitable" ! Qty || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || X1 || || MA05-2 || MPE 088-2-010 |- | 2 || R1, R2 || 0R || R0805 || SMD-0805 0,00 |- | 3 || C1, C2, C3 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 4 || R6, R8, R11, R16 || 15k || R0805 || RND 0805 1 15K |- | 1 || R13 || 1k5 || R0805 || SMD-0805 1,50K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 1 || R5 || 270 || R0805 || SMD-0805 270 |- | 1 || D6 || 2V4 || SOD80C || TZMC2V4 |- | 4 || R9, R17, R18, R19 || 2k2 || R0805 || RND 0805 1 2,2K |- | 2 || R14, R15 || 330 || R1206 || RND 155HP06 CJ |- | 2 || R7, R10 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || T1 || IRF7470 || SO08-IRF || IRF 7470 |- | 1 || IC1 || LM317LD || SO08 || |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB10CA || SMBJ || P6SMB 10CA SMD |} =Download= * [[Datei:resol_71005014.zip]] EAGLE-Dateien für die reverse engineerte Leiterkarte als auch der verbesserten Version [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 4d8df64c34e2c671f748ed9e9cb94fa60319813b 1791 1790 2022-11-02T21:55:21Z Chris 2 wikitext text/x-wiki =Reparatur= Ab und zu geht auch was kaputt. So schrieb mich vor einiger Zeit Erhard an, der an seinem DeltaSol ES einen Resol DL2 Datenlogger betreibt. Obwohl beide Geräte für sich funktionieren, kamen keine Daten mehr an. An der VBus-Schnittstelle lag ohne Datenlogger nur ein eine Spannung von etwa 4 V an, mit Datenlogger brach die Spannung weiter auf ca. 2,7 V ein. Bei erwarteten ca. 8 Volt und den definierten Schwellen in der [[Datei:VBus-Protokollspezifikation.pdf|Protokollspezifikation]] ist die Begründung für die Funktionslosigkeit gefunden - aber nicht die Ursache. Nach kurzer Recherche bin ich auf einen Thread bei [https://community.home-assistant.io/t/resol-vbus/5304/25 Home Assistant] gestoßen, in dem ein u. a. VBus-Modul gezeigt wird. Rechts oben prankt die Bezeichnung 71005014. In einem Katalog über Resol-Produkte ließ sich zumindest ansatzweise erkennen, dass das Modul auch in anderen Reglern verwendet wird, also ging die Suche nach Ersatz los - und tatsächlich ließ sich das Modul für schlappe 12 Euro auf eBay finden. Es ging ein bisschen Zeit ins Land, bis eine weitere Anfrage bzgl. defektem VBus-Interface kam. Also den Mailthread herausgekramt und nochmal nachgefragt, wie die Reparatur ausging - leider noch nicht ganz so erfolgreich, da das Modul nicht passt. Statt der geraden Stiftleiste ist eine gewinkelte nötig und die Bestückung weicht ab. Also einfach mal gefragt, ob Erhard das Defekte Modul und den Ersatz schicken möchte - und ein paar Tage später lagen die Boards auf dem Tisch: <gallery> Resol 71005014 pcb ebay top.jpg | Oberseite der Leiterkarte von eBay Resol 71005014 pcb ebay bot.jpg | Unterseite der Leiterkarte von eBay Resol 71005014 pcb regler top.jpg | Oberseite der Leiterkarte vom Regler Resol 71005014 pcb regler bot.jpg | Unterseite der Leiterkarte vom Regler </gallery> Abgesehen von der leicht unterschiedlichen Farbe des Lötstopps (und des Weißabgleichs) sieht man der Leiterkarte aus dem Regler deutlich an, dass sie Temperatur im Bereich des Chips links unten gesehen hat. Beim dem Bauteil handelt es sich um einen LM317 - also ein Spannungsregler. ein kurzer Blick ins Datenblatt verrät, dass links unten der Adjust-Pin ist, der Pin links oben der Eingang und die Pins dazwischen die Ausgänge sind. Da die Regler üblicherweise einen Spannungsteiler und damit 2 Widerstände zum Einstellen der Spannung brauchen, wird der Regler wohl anders verwendet wird: Der 24,3 Ohm-Widerstand befindet sich zwischen Ausgang und Adjust, mehr sieht man leider nicht. In diesem Sinne "glücklicherweise" ist der LM317 bei Ersatzleiterkarte der Käfer nicht bestückt - die Leiterbahnen zeigen: die Ausgangspins sind zwar miteinander verbunden, aber das war's auch schon. Ein Via führt lediglich zum Adjust-Pin. Etwas weiter unten im [https://www.ti.com/lit/ds/symlink/lm317l-n.pdf#page=14 Datenblatt] ist auch diese Anwendung aufgeführt: Stromquelle. Deren Stärke lässt sich sehr einfach nach <math>I_\textrm{out} = \frac{1.2}{R}</math> berechnen. Mit 24,3 Ohm ergibt das (Trommelwirbel) 49,4 mA. Die Pins zurückverfolgt wird an den rechten beiden 9 V eingespeist und geschaut, welcher Strom vom Ausgang der Stromquelle nach Masse fließt - unspektakuläre 1,2 mA. Ein LM317 liegt noch herum, also runter das olle Teil und rauf mit dem Neuen. Nochmals nachgemessen: um die 50 mA. Super! Fall erledigt, eintüten und ab dafür! =Reverse Engineering= Äh, nein. So läuft das hier nicht. Aufmerksame Leser werden schon bemerkt haben, dass die Bilder oben (nicht ganz) zufällig die gleiche Größe haben und sehr gleichartig abgebildet sind. Es gibt noch ein weiteres Foto und eine bearbeitete Version - beim Foto fehlen ein paar Bauteile, bei der Bearbeitung haben alle Komponenten einen Namen bekommen und eine Innenbeschaltung hat es auf das Foto geschafft: <gallery> resol 71005014 pcb ebay top desoldered.jpg | Bauteile entfernt resol 71005014 pcb ebay top refdes.jpg | Mit Namen und Innenbeschaltung resol 71005014 pcb regler top all layers.jpg | Alle Lagen überlagert </gallery> Warum Namen? Zugegebenermaßen mag das bei der Komplexität der Schaltung etwas übertrieben sein, aber es hilft, den Schaltplan zu entflechten und im Anschluss beim Placement. Auf eine weitere Lage in naint.net werden Vias markiert, für die wenigen Leiterbahnen auf der Unterseite gibt es ebenfalls eine. ==Bauteile== D3 ist eine mit an Sicherheit grenzender Wahrscheinlichkeit eine TVS-Diode. Nach etwas längerer [https://rtellason.com/semiconductorlogos.html Suche nach dem Logo] stellte sich heraus, dass es sich um ein Teil von General Semiconductor (heute Vishay) handelt. Die Suche nach "KM 66A" brachte zumindest bei Google erst einmal nur eine öffentliche Toilette in Österreich (wen es interessiert: A12 Intall Autobahn, bei km 66,28 Richtung Zams). Hm, das war wohl ein... [https://www.youtube.com/results?search_query=csi+sunglass+moment ...griff ins Klo]?! Unstrittig ist jedenfalls, dass es sich um ein SMB-Gehäuse handelt. Nach etwas mehr Sucherei und dem Auffinden einer alten Version eines Dokuments zum [http://matthieu.benoit.free.fr/cross/competitive/general_semi/marking.pdf PDD Marking] müsste es sich um eine [https://www.vishay.com/docs/88392/smbj.pdf SMBJ7.0A] handeln. Auch wenn mir Parameter wie Breakdown Voltage und Stand-off Voltage etwas niedrig vorkommen - die Angabe deckt sich mit dem vorgeschlagenen Bauteil in der [[Datei:VBus-Protokollspezifikation.pdf|Protokollspezifikation]] D5, die Diode im MiniMelf-Gehäuse, musste kurz die Leiterkarte verlassen um gemessen zu werden, ähnlich wie die Kondensatoren. Bei der Diode handelt es sich mutmaßlich um eine Z-Diode mit 4,7 V Rückwärtsspannung. Widerstände im 0805 Gehäuse haben dankenswerterweise noch Beschriftungen, hier ist einzig R9 etwas tricky: Ist das nun 1091 oder 1601? Ersteres würde 1,09 kOhm bedeuten, letzteres 1,6 kOhm. Da 1,09 in den [[wpde:E-Reihe|E-Reihen]] nicht existiert, muss es wohl 1,6 kOhm sein. Ein anderer Hinweis ist natürlich, dass die 9 rechts unten abgeschrägt ist (ähnlich wie die 2). Eine kleine Gemeinheit: R9 und R11 sind auf den beiden Boards unterschiedlich - eine Erklärung hierzu findet sich weiter unten. T1 dient vermutlich zum Senden der Daten, indem er die VBus-Leitung nach Masse kurschließt. Hätte es mir im Master etwas eleganter vorgestellt, aber warum auch nicht - es funktioniert. Wobei der FET, ein Fairchild RFD14N05L, mit seinen 14 A natürlich durchaus wohlwollend dimensioniert ist. Bei IC2 handelt es sich um einen Komparator, genau genommen einem TI TLC3702; IC3 ist ein Quad 2 Input NAND Gatter mit Schmitt-Trigger-Eingängen. Noch einmal in die Protokollspezifikation gespickt: da wurde das Rad auf keinen Fall neu erfunden. Da muss man beim Reverse Engineering eigentlich nicht viel können und auch kein schlechtes Gewissen haben. Einzig unklar sind die beiden unbestückten Bauteile links oberhalb von IC1. Den Footprints nach zu urteilen dürfte "?1" entweder ein Widerstand oder ein Kondensator sein, "?2" wäre in Hinblick auf D5 ebenfalls eine Diode im MiniMelf-Package. Mehr dazu weiter unten. ==Schaltplan== Den Schaltplan abzuzeichnen in etwa so schnell wie den Artikel bis hier zu schreiben. Auch wenn die Schaltung sehr nah am Referenzschaltplan ist, kleine Unterschiede gibt es doch: D5 ist dort eine gewöhnliche Kleinsignaldiode, die Überspannung nach Vcc ableitet, auf dem Modul ist es mit einer Z-Diode, die nach Masse "verbrennt" etwas besser gelöst. Um es kurz zu machen, so schaut's aus: <gallery> resol_71005014_sch.png | Schaltplan der Basisvariante resol_71005014_M_5V_sch.png | Variante für 5V-Master resol_71005014_S_3V3_sch.png | Variante für 3,3V-Slaves resol_71005014_brd.png | Layout der Basisvariante </gallery> Erhard war so freundlich und hat noch weitere Fotos vom Innenleben des Reglers geschickt (siehe [[link]]) und noch ein paar Messungen durchgeführt. So liegen an dem mit 12V bezeichneten Pin 8 von X1 stolze 20,7 V an. Plausibel? Laut Bild hat die DeltaSol ES ein Transformator mit 12,5 V am Ausgang. Das ergibt einen Spitzenwert von 17,7 V - ohne Berücksichtigung des Gleichrichters und natürlich der etwas höheren Leerlaufspannung. Also ja, plausibel. Die andere Versorgung sowie die IO-Spannung beläuft sich auf 3,3 V. ==Kleine Sünden== Nun wird auch in Hinblick auf die TVS-Diode ein Schuh draus: Die Stromquelle begrenzt, wie oben bereits berechnet, auf etwa 50 mA auf dem Bus. Der Spannungsabfall über diesen dürfte auf jeden Fall unter 2 V liegen. Dementsprechend müsste man auf dem Bus um die 18 V sehen - was aber nicht der Fall ist. Die TVS-Diode ist im Breaktdown und wandelt die Spannungsdifferenz in Wärme um. Da haben wir unsere ca. 8,2 V. Hurra. Nicht. In der Schaltung fließen auf jeden Fall 50 mA, bei den 8,2 V ist das eine Leistung von rechnerisch 410 mW. Der Rest bleibt am LM317 (und seinem Serienwiderstand) hängen, also (20,7 - 8,2 V) * 50 mA = 625 mW. Etwas mehr als 1 Watt für die unbenutzte Kommunikationssschnittstelle, wenn der Regler im Idle ist? Hui. Ok, sobald die Relais anziehen sinkt die Spannung und damit Verlustleistung ein bisschen, aber erstrebenswert ist das nicht. Wird, bei Kommunikation, VBUS nach Masse gezogen, bleibt fast die volle Leistung am armen LM317 hängen - zwar nur kurzzeitigig aber Stress ist Stress. Das erklärt nun auch die Verfärbung der Leiterkarte und ggf. das verfrühte Ableben des ICs. Was macht das eine Watt aus? Bei 24/7-Betrieb im Jahr ca. 8,8 kWh, bei 40 ct/kWh sind das knapp 3,5 Euro. Nicht viel aber nicht nichts, plus leidende Elektronik. Wie man es besser machen kann? Verschiedene Ansätze sind möglich: * Auf der Main-PCB 12 V geregelt bereitstellen oder Spannung verringern - verringert auch die Stromaufnahme der anderen 12V-Komponenten (Relais), die der Schnittstelle aber nur um ein knappes halbes Watt * Zweiter Regler für die Schnittstelle: Spannung auf 8,nochwas Volt regeln und den Strom auf 50 mA begrenzen. So wird die TVS-Diode nicht leitend und wenn nicht kommuniziert wird, wird auch kein Strom sinnlos verbraten. * Breakdown-Voltage der TVS-Diode erhöhen. Höhere Spannung am Bus (und damit Specbruch) * Vorige Punkte in Kombination Sollte jemand tatsächlich so verrückt sein und ein alternatives Modul entwickeln, scheiden Änderungen an der Main-PCB natürlich aus, also bleiben die letzten 3 Punkte. ==Die Widerstände== Wie bereits erwähnt, weichen die Widerstände R9 und R11 auf den beiden Boards etwas ab: {| class="wikitable" ! Variante || R9 || R11 || unterer Knoten || oberer Knoten |- | Regler || 2,4k || 1,4k || 60,0 % || 61,1 % |- | Ersatz || 1,6k || 820R || 61,0 % || 68,7 % |} Multipliziert man die Verhältnisse mit 3,3 und 5 V, findet man bekannte Werte: Bei der Leiterkarte aus dem Regler und 5 V ergeben sich 3,00 und 3,25 V, was den Schaltschwellen für einen Master ergibt, für die Ersatzleiterkarte und einer Spannung von 3,3 V kommen 2,27 und 2,02 V heraus, was noch immer recht gut zu den Werten eines Slaves passt. Nur passt nichts so richtig zu dem tatsächlichen Einsatz - allerdings kann man hier die Kirche im Dorf lassen: Es geht lediglich darum, High und Low möglichst ohne Gezappel zu unterscheiden. Auf ein paar hundert Millivolt kommt es bei den Schaltschwellen sicher nicht an. Überspitzt gesagt könnte man den ganzen Bohei mit Komparator und Optokoppler durch einen Spannungsteiler mit Tiefpass ersetzen. Dürfte in den allermeisten Fällen genauso gut funktionieren. =Verbesserte Version= '''Ungetestet''' Die Unzulänglichkeit des unnötig hohen Stromverbrauches der Originalversion ist Grund genug, das Design anzufassen. Statt den Strom zu begrenzen und die zu hohe Spannung in der TVS-Diode zu verbraten, läuft der LM317 nun als Spannungsregler mit etwa 8,2 V Ausgangsspannung. Der Strom wird über zwei parallele 330 Ohm-Widerstände auf knapp 50 mA begrenzt. Die TVS-Diode hat nun eine Breakdown-Spannung von 10 V - die restlichen Bauteile sind dadurch weiterhin gegen Überspannung geschützt und die "Gefahr", dass sinnlos Leistung verbraten wird, vom Tisch. Die Logik-Gatter werden durch die bekannte und erprobte Beschaltung der Komparatoren ersetzt. Zusätzlich hat die (optionale) Z-Diode ihren Weg in den Schaltplan gefunden. Zum Invertieren von UART_TX wird ein BSS138 eingesetzt, der einen etwas einfacher erhältlichen IRF7470 treibt. Dieser kann zwar deutlich weniger Strom als der ursprüngliche treiben, muss er aber auch nicht. Schlussendlich ist die Leiterkarte auch etwas geschrumpt: <gallery> 71005014i_sch.png | Schaltplan Basisvariante 71005014i_M_3V3_sch.png | Schaltplan 3,3 V Master 71005014i_M_5V_sch.png | Schaltplan 5,0 V Master 71005014i_S_3V3_sch.png | Schaltplan 3,3 V Slave </gallery> <gallery> 71005014i_top.png | Bestückungsplan Oberseite 71005014i_top_m_3v3.png | Bestückungsplan Oberseite 3,3 V Master 71005014i_bot.png | Unterseite Layout </gallery> Die BOM umfasst hier lediglich die (wohl interessanteste) Variante für den 3,3 V Master. Bitte beachten, dass die in EAGLE generierbare BOM nur die Bestellcodes für diese Variante enthalten. {| class="wikitable" ! Qty || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || X1 || || MA05-2 || MPE 088-2-010 |- | 2 || R1, R2 || 0R || R0805 || SMD-0805 0,00 |- | 3 || C1, C2, C3 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 4 || R6, R8, R11, R16 || 15k || R0805 || RND 0805 1 15K |- | 1 || R13 || 1k5 || R0805 || SMD-0805 1,50K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 1 || R5 || 270 || R0805 || SMD-0805 270 |- | 1 || D6 || 2V4 || SOD80C || TZMC2V4 |- | 4 || R9, R17, R18, R19 || 2k2 || R0805 || RND 0805 1 2,2K |- | 2 || R14, R15 || 330 || R1206 || RND 155HP06 CJ |- | 2 || R7, R10 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || T1 || IRF7470 || SO08-IRF || IRF 7470 |- | 1 || IC1 || LM317LD || SO08 || |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB10CA || SMBJ || P6SMB 10CA SMD |} =Download= * [[Datei:resol_71005014.zip]] EAGLE-Dateien für die reverse engineerte Leiterkarte als auch der verbesserten Version [[Kategorie:Solaranlage]] [[Kategorie:VBus]] b2c78d7ad677213b96be8e084f468513ae02ac59 Hauptseite 0 1 1792 1740 2022-11-02T21:58:49Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *02.11.2022 Ein [[Resol 71005014 Schnittstellenadapter]] wurde repariert und verbessert *02.11.2022 Warum zur Abwechslung nicht einmal paar [[Resol - Zerlegt|Resol Geräte zerlegen]] *23.12.2021 Es wird heimelig zu Weihnachten: ein [[LED-Lagerfeuer]] *13.12.2021 Mal wieder ein VBus-Decoder - jetzt für den [[VBus-Decoder/Adapter_für_den_ESP8266|ESP8266]] *07.09.2021 Eine aktualisierte Untersuchung des [[ECL-Bus-Protokoll]]s *12.07.2021 Der Pythoncode der [[MCP-USB-Bridge]] ist auf GitHub umgezogen und spricht nun mit dem MCP2210 (SPI) *26.02.2021 Und noch ein Update für den VBus-Decoder: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]] und [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]], sowie einem einfachen [[VBus-Decoder#Protokoll-Analysator|Protokoll-Analysator]] *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> bca2468285985eec9d393464603a150772e603f0 1818 1792 2022-11-11T22:09:09Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *11.11.2022 Weitere Informationen zu den [[Prozeda-Decoder#Display|Displaydaten]] beim [[Prozeda-Decoder]] *10.11.2022 Ein CitrinSolar CS 1.3 wurde [[Resol_-_Zerlegt#CitrinSolar_CS_1.3|zerlegt]] und [[Resol - Reparaturen|repariert]] *02.11.2022 Ein [[Resol 71005014 Schnittstellenadapter]] wurde repariert und verbessert *02.11.2022 Warum zur Abwechslung nicht einmal paar [[Resol - Zerlegt|Resol Geräte zerlegen]] *23.12.2021 Es wird heimelig zu Weihnachten: ein [[LED-Lagerfeuer]] *13.12.2021 Mal wieder ein VBus-Decoder - jetzt für den [[VBus-Decoder/Adapter_für_den_ESP8266|ESP8266]] *07.09.2021 Eine aktualisierte Untersuchung des [[ECL-Bus-Protokoll]]s *12.07.2021 Der Pythoncode der [[MCP-USB-Bridge]] ist auf GitHub umgezogen und spricht nun mit dem MCP2210 (SPI) *26.02.2021 Und noch ein Update für den VBus-Decoder: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]] und [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]], sowie einem einfachen [[VBus-Decoder#Protokoll-Analysator|Protokoll-Analysator]] *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> 47b4d5bb2fbc720d6171cebd06c2e48432739361 1829 1818 2022-11-24T20:24:24Z Chris 2 wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *24.11.2022 Beim VBus-ESP8266-Adapter kann es [[VBus-Decoder/Adapter_für_den_ESP8266#Fehlerhafter_Datenempfang|Fehler beim Datenempfang]] geben *22.11.2022 Kleine Korrektur beim [[VBus-Decoder/Adapter_für_RS-232|VBus-Adapter für RS-232]] *11.11.2022 Weitere Informationen zu den [[Prozeda-Decoder#Display|Displaydaten]] beim [[Prozeda-Decoder]] *10.11.2022 Ein CitrinSolar CS 1.3 wurde [[Resol_-_Zerlegt#CitrinSolar_CS_1.3|zerlegt]] und [[Resol - Reparaturen|repariert]] *02.11.2022 Ein [[Resol 71005014 Schnittstellenadapter]] wurde repariert und verbessert *02.11.2022 Warum zur Abwechslung nicht einmal paar [[Resol - Zerlegt|Resol Geräte zerlegen]] *23.12.2021 Es wird heimelig zu Weihnachten: ein [[LED-Lagerfeuer]] *13.12.2021 Mal wieder ein VBus-Decoder - jetzt für den [[VBus-Decoder/Adapter_für_den_ESP8266|ESP8266]] *07.09.2021 Eine aktualisierte Untersuchung des [[ECL-Bus-Protokoll]]s *12.07.2021 Der Pythoncode der [[MCP-USB-Bridge]] ist auf GitHub umgezogen und spricht nun mit dem MCP2210 (SPI) *26.02.2021 Und noch ein Update für den VBus-Decoder: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]] und [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]], sowie einem einfachen [[VBus-Decoder#Protokoll-Analysator|Protokoll-Analysator]] *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> a56752d2fccd59d77ee727993def7d41c25d8017 Resol - Zerlegt 0 782 1793 1770 2022-11-02T21:59:45Z Chris 2 VBus-Schnittstellenadapter (71005014) hinzugefügt wikitext text/x-wiki Auf die inneren Werte kommt es an. Damit nicht jeder sein Equipment auseinanderschrauben muss, hier eine Sammlung verschiedener Geräte aus dem Hause Resol: =DeltaSol ES (71002246)= Der DeltaSol ES ist ein Regler mit 36 vorprogrammierten Solar- und Heizanlagen. Vielen Dank an Erhard für die Aufnahmen! <gallery> Deltasol_es_front.jpg | Regler von vorne Deltasol_es_left.jpg | Ansicht von innen links Deltasol_es_total.jpg | Ansicht von innen Deltasol_es_right.jpg | Ansicht von innen rechts </gallery> Hauptkomponenten: * Eingänge Temperatursensoren ** SRDA3.3-4: Low Capacitance TVS Array ** TI HC4051: Analog Mux ** TI LM324: Op-Amp ** TI HC04: Hex Inverter * RS232-Interface ** Intersil 3232ECBZ: RS232-Transceiver * Schaltkontakte ** Finder 34.51.7.012.0010: Printrelais 12VDC Spule, 400VAC 6A/1500VA Kontakt ** Relais Beschriftung nicht lesbar ** Omron G3MB-202P: Halbleiterrelais 5VDC Eingang, 240VAC 2A Last ** TI ULN2???: Treiber für Relais ** TI MC???: Vermutlich Latch/Schieberegister/IO-Expander * Stromversorgung ** MS 5233: 12,5V, 0,4A Transformator ** Spannungsregler Beschriftung nicht lesbar * Brains ** Mikrocontroller Beschriftung nicht lesbar ** RTC Beschriftung nicht lesbar ** Holtek HT1621B: LCD Treiber 32x4 =DL2 (71007402)= Der DL2 ist ein Datenlogger, der neben dem Loggen auf eine SD-Karte auch eine Schnittstelle ins Netzwerk (Ethernet) bereitstellt. Vielen Dank an Erhard für die Aufnahmen! <gallery> Resol_DL2_top.jpg | Oberseite Resol_DL2_bot.jpg | Unterseite </gallery> Hauptkomponenten: * Atmel AT91SAM9260: ARM Mikrocontroller, 180 MHz * Atmel ???: Vermutlich NOR-Flash * Samsung K9F2G08U0B: 256Mbit + 8 MBit NAND Flash * Micron MT48LC16M16A2: 256 Mbit SDRAM * Davicom DM9161: 100BASE-TX Phy =VBus-Schnittstellenadapter (71005014)= siehe [[Resol 71005014 Schnittstellenadapter]] Vielen Dank an Erhard für die Aufnahmen! [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 11b7e8c63f0d2000c1a9f98ef4cf341140892f19 1794 1793 2022-11-02T22:00:04Z Chris 2 /* VBus-Schnittstellenadapter (71005014) */ wikitext text/x-wiki Auf die inneren Werte kommt es an. Damit nicht jeder sein Equipment auseinanderschrauben muss, hier eine Sammlung verschiedener Geräte aus dem Hause Resol: =DeltaSol ES (71002246)= Der DeltaSol ES ist ein Regler mit 36 vorprogrammierten Solar- und Heizanlagen. Vielen Dank an Erhard für die Aufnahmen! <gallery> Deltasol_es_front.jpg | Regler von vorne Deltasol_es_left.jpg | Ansicht von innen links Deltasol_es_total.jpg | Ansicht von innen Deltasol_es_right.jpg | Ansicht von innen rechts </gallery> Hauptkomponenten: * Eingänge Temperatursensoren ** SRDA3.3-4: Low Capacitance TVS Array ** TI HC4051: Analog Mux ** TI LM324: Op-Amp ** TI HC04: Hex Inverter * RS232-Interface ** Intersil 3232ECBZ: RS232-Transceiver * Schaltkontakte ** Finder 34.51.7.012.0010: Printrelais 12VDC Spule, 400VAC 6A/1500VA Kontakt ** Relais Beschriftung nicht lesbar ** Omron G3MB-202P: Halbleiterrelais 5VDC Eingang, 240VAC 2A Last ** TI ULN2???: Treiber für Relais ** TI MC???: Vermutlich Latch/Schieberegister/IO-Expander * Stromversorgung ** MS 5233: 12,5V, 0,4A Transformator ** Spannungsregler Beschriftung nicht lesbar * Brains ** Mikrocontroller Beschriftung nicht lesbar ** RTC Beschriftung nicht lesbar ** Holtek HT1621B: LCD Treiber 32x4 =DL2 (71007402)= Der DL2 ist ein Datenlogger, der neben dem Loggen auf eine SD-Karte auch eine Schnittstelle ins Netzwerk (Ethernet) bereitstellt. Vielen Dank an Erhard für die Aufnahmen! <gallery> Resol_DL2_top.jpg | Oberseite Resol_DL2_bot.jpg | Unterseite </gallery> Hauptkomponenten: * Atmel AT91SAM9260: ARM Mikrocontroller, 180 MHz * Atmel ???: Vermutlich NOR-Flash * Samsung K9F2G08U0B: 256Mbit + 8 MBit NAND Flash * Micron MT48LC16M16A2: 256 Mbit SDRAM * Davicom DM9161: 100BASE-TX Phy =VBus-Schnittstellenadapter (71005014)= siehe [[Resol 71005014 Schnittstellenadapter]] Vielen Dank an Erhard für die Bereitstellung der Leiterkarten! [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 6adaea177bf96292a8ebac361fc9e6b6944b44c8 1797 1794 2022-11-10T21:17:11Z Chris 2 CitrinSolar CS 1.3 hinzugefügt wikitext text/x-wiki Auf die inneren Werte kommt es an. Damit nicht jeder sein Equipment auseinanderschrauben muss, hier eine Sammlung verschiedener Geräte aus dem Hause Resol: =DeltaSol ES (71002246)= Der DeltaSol ES ist ein Regler mit 36 vorprogrammierten Solar- und Heizanlagen. Vielen Dank an Erhard für die Aufnahmen! <gallery> Deltasol_es_front.jpg | Regler von vorne Deltasol_es_left.jpg | Ansicht von innen links Deltasol_es_total.jpg | Ansicht von innen Deltasol_es_right.jpg | Ansicht von innen rechts </gallery> Hauptkomponenten: * Eingänge Temperatursensoren ** SRDA3.3-4: Low Capacitance TVS Array ** TI HC4051: Analog Mux ** TI LM324: Op-Amp ** TI HC04: Hex Inverter * RS232-Interface ** Intersil 3232ECBZ: RS232-Transceiver * Schaltkontakte ** Finder 34.51.7.012.0010: Printrelais 12VDC Spule, 400VAC 6A/1500VA Kontakt ** Relais Beschriftung nicht lesbar ** Omron G3MB-202P: Halbleiterrelais 5VDC Eingang, 240VAC 2A Last ** TI ULN2???: Treiber für Relais ** TI MC???: Vermutlich Latch/Schieberegister/IO-Expander * Stromversorgung ** MS 5233: 12,5V, 0,4A Transformator ** Spannungsregler Beschriftung nicht lesbar * Brains ** Mikrocontroller Beschriftung nicht lesbar ** RTC Beschriftung nicht lesbar ** Holtek HT1621B: LCD Treiber 32x4 =DL2 (71007402)= Der DL2 ist ein Datenlogger, der neben dem Loggen auf eine SD-Karte auch eine Schnittstelle ins Netzwerk (Ethernet) bereitstellt. Vielen Dank an Erhard für die Aufnahmen! <gallery> Resol_DL2_top.jpg | Oberseite Resol_DL2_bot.jpg | Unterseite </gallery> Hauptkomponenten: * Atmel AT91SAM9260: ARM Mikrocontroller, 180 MHz * Atmel ???: Vermutlich NOR-Flash * Samsung K9F2G08U0B: 256Mbit + 8 MBit NAND Flash * Micron MT48LC16M16A2: 256 Mbit SDRAM * Davicom DM9161: 100BASE-TX Phy =VBus-Schnittstellenadapter (71005014)= siehe [[Resol 71005014 Schnittstellenadapter]] Vielen Dank an Erhard für die Bereitstellung der Leiterkarten! =CitrinSolar CS 1.3= Vielen Dank an Oliver für die Aufnahmen! <gallery> citrinsolar_cs_13_aussen.jpg | Regler von Außen citrinsolar_cs_13_innen.jpg | Regler von Innen </gallery> Anders als die Resol-Regler die ich bisher gesehen habe, verwendet dieser ein Schaltnetzteil zur Versorgung und weist keine Modularität (z. B. für die VBus-Schnittstelle) auf. Hauptkomponenten * Stromversorgung ** Power integrations TNY274GN: Schaltnetzteil-Controller * Brains ** Infineon MB9AFB44NA: ARM Mikrocontroller 256 KByte ** Epson RX-4045: RTC * Leistungsstufe ** MOC3053 oder MOC3063: Optokoppler mit Triac-Treiber ** NXP? BTA225B-800B: Triac 800 V, 25 A [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 2ff7f506363fc402b5d8573272873b10ef48de06 1803 1797 2022-11-10T21:29:27Z Chris 2 wikitext text/x-wiki Auf die inneren Werte kommt es an. Damit nicht jeder sein Equipment auseinanderschrauben muss, hier eine Sammlung verschiedener Geräte aus dem Hause Resol: =DeltaSol ES (71002246)= Der DeltaSol ES ist ein Regler mit 36 vorprogrammierten Solar- und Heizanlagen. Vielen Dank an Erhard für die Aufnahmen! <gallery> Deltasol_es_front.jpg | Regler von vorne Deltasol_es_left.jpg | Ansicht von innen links Deltasol_es_total.jpg | Ansicht von innen Deltasol_es_right.jpg | Ansicht von innen rechts </gallery> Hauptkomponenten: * Eingänge Temperatursensoren ** SRDA3.3-4: Low Capacitance TVS Array ** TI HC4051: Analog Mux ** TI LM324: Op-Amp ** TI HC04: Hex Inverter * RS232-Interface ** Intersil 3232ECBZ: RS232-Transceiver * Schaltkontakte ** Finder 34.51.7.012.0010: Printrelais 12VDC Spule, 400VAC 6A/1500VA Kontakt ** Relais Beschriftung nicht lesbar ** Omron G3MB-202P: Halbleiterrelais 5VDC Eingang, 240VAC 2A Last ** TI ULN2???: Treiber für Relais ** TI MC???: Vermutlich Latch/Schieberegister/IO-Expander * Stromversorgung ** MS 5233: 12,5V, 0,4A Transformator ** Spannungsregler Beschriftung nicht lesbar * Brains ** Mikrocontroller Beschriftung nicht lesbar ** RTC Beschriftung nicht lesbar ** Holtek HT1621B: LCD Treiber 32x4 =DL2 (71007402)= Der DL2 ist ein Datenlogger, der neben dem Loggen auf eine SD-Karte auch eine Schnittstelle ins Netzwerk (Ethernet) bereitstellt. Vielen Dank an Erhard für die Aufnahmen! <gallery> Resol_DL2_top.jpg | Oberseite Resol_DL2_bot.jpg | Unterseite </gallery> Hauptkomponenten: * Atmel AT91SAM9260: ARM Mikrocontroller, 180 MHz * Atmel ???: Vermutlich NOR-Flash * Samsung K9F2G08U0B: 256Mbit + 8 MBit NAND Flash * Micron MT48LC16M16A2: 256 Mbit SDRAM * Davicom DM9161: 100BASE-TX Phy =VBus-Schnittstellenadapter (71005014)= siehe [[Resol 71005014 Schnittstellenadapter]] Vielen Dank an Erhard für die Bereitstellung der Leiterkarten! =CitrinSolar CS 1.3= Vielen Dank an Oliver für die Aufnahmen! <gallery> citrinsolar_cs_13_aussen.jpg | Regler von Außen citrinsolar_cs_13_innen.jpg | Regler von Innen </gallery> Anders als die Resol-Regler die ich bisher gesehen habe, verwendet dieser ein Schaltnetzteil zur Versorgung und weist keine Modularität (z. B. für die VBus-Schnittstelle) auf. Hauptkomponenten * Stromversorgung ** Power integrations TNY274GN: Schaltnetzteil-Controller * Brains ** Infineon MB9AFB44NA: ARM Mikrocontroller 256 KByte ** Epson RX-4045: RTC * Leistungsstufe ** MOC3053 oder MOC3063: Optokoppler mit Triac-Treiber ** NXP? BTA225B-800B: Triac 800 V, 25 A [[Kategorie:Solaranlage]] [[Kategorie:VBus]] [[Kategorie:Zerlegt]] 645d54f74218908e5880548594e8e6a381d3c740 Datei:Citrinsolar cs 13 aussen.jpg 6 803 1795 2022-11-10T21:16:27Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Citrinsolar cs 13 innen.jpg 6 805 1798 2022-11-10T21:21:01Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Resol - Reparaturen 0 806 1799 2022-11-10T21:27:53Z Chris 2 Seite erstellt wikitext text/x-wiki =CitrinSolar CS 1.3 VBus-Interface= Oliver hat die Schaltung für sein CitrinSolar CS 1.3 nachgebaut und stand vor einem Problem: Beim Anschließen hat er sich bei den Pins am Regler verzählt - anschließend kamen statt der knapp 9 V nur noch unter 1 V aus der VBus-Schnittstelle. Telegramme kamen zwar noch raus, aber halt außerhalb der Spec. Die Reglerreihe ist etwas moderner/anders aufgebaut was ich bis jetzt von Resol [[Resol - Zerlegt|gesehen]] habe - und weniger modular. Ein [[Resol 71005014 Schnittstellenadapter|71005014 Schnittstellenadapter]] ist dementsprechend nicht vorhanden. Messmittel und Wissen sind vorhanden, also: <pre> Ich habe gerade nochmal Messungen gemacht und weiß grad etwas mehr. Im Regler gibts einen Spannungsregler, der kanpp 10.2V generiert. Zwischen den VBUS Leitungen ist dann eine 8.1V Z Diode, die die Spannung auf dem Bus begrenzt. …Und an der Stelle hängts grad noch bei mir. Der 10.2V Regler läuft, aber an der Z-Diode ist an der V+ Leitung nur noch 0.1V. D.h. hier ist irgendwas dazwischen defekt… </pre> ein paar Tage später kam dann die Erfolgsmeldung: <pre> Die Anlage läuft wieder. Am VBUS war eine BAT54S auf dem VBUS- durch und hat den Bus auf GND kurzgeschlossen. Die ausgelötete Stelle war die BAT54S. Heute eingelötet, jetzt geht alles. Auch der Adapter, den ich auf Basis deiner Raspi Schaltung mit dem Optokoppler gebaut hab, läuft. </pre> <gallery> citrinsolar_cs13_diode1.jpg | Ort der defekten BAT54S citrinsolar_cs13_diode2.jpg | Detailaufnahme (Diode entfernt) </gallery> Einen Überblick über den Regler gibt es im Artikel [[Resol - Zerlegt#CitrinSolar_CS_1.3|Resol - Zerlegt]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] [[Kategorie:Reparatur]] 7e4efff22b3f0f970e0910420c76005633a2afad 1802 1799 2022-11-10T21:28:51Z Chris 2 wikitext text/x-wiki =CitrinSolar CS 1.3 VBus-Interface= Oliver hat die Schaltung für sein CitrinSolar CS 1.3 nachgebaut und stand vor einem Problem: Beim Anschließen hat er sich bei den Pins am Regler verzählt - anschließend kamen statt der knapp 9 V nur noch unter 1 V aus der VBus-Schnittstelle. Telegramme kamen zwar noch raus, aber halt außerhalb der Spec. Die Reglerreihe ist etwas moderner/anders aufgebaut was ich bis jetzt von Resol [[Resol - Zerlegt|gesehen]] habe - und weniger modular. Ein [[Resol 71005014 Schnittstellenadapter|71005014 Schnittstellenadapter]] ist dementsprechend nicht vorhanden. Messmittel und Wissen sind vorhanden, also: <pre> Ich habe gerade nochmal Messungen gemacht und weiß grad etwas mehr. Im Regler gibts einen Spannungsregler, der kanpp 10.2V generiert. Zwischen den VBUS Leitungen ist dann eine 8.1V Z Diode, die die Spannung auf dem Bus begrenzt. …Und an der Stelle hängts grad noch bei mir. Der 10.2V Regler läuft, aber an der Z-Diode ist an der V+ Leitung nur noch 0.1V. D.h. hier ist irgendwas dazwischen defekt… </pre> ein paar Tage später kam dann die Erfolgsmeldung: <pre> Die Anlage läuft wieder. Am VBUS war eine BAT54S auf dem VBUS- durch und hat den Bus auf GND kurzgeschlossen. Die ausgelötete Stelle war die BAT54S. Heute eingelötet, jetzt geht alles. Auch der Adapter, den ich auf Basis deiner Raspi Schaltung mit dem Optokoppler gebaut hab, läuft. </pre> <gallery> citrinsolar_cs_13_diode1.jpg | Ort der defekten BAT54S citrinsolar_cs_13_diode2.jpg | Detailaufnahme (Diode entfernt) </gallery> Einen Überblick über den Regler gibt es im Artikel [[Resol - Zerlegt#CitrinSolar_CS_1.3|Resol - Zerlegt]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] [[Kategorie:Reparatur]] 2727806517457b67bda42e93e5fc52d7f8e021c9 1819 1802 2022-11-11T22:13:09Z Chris 2 Anmerkung zur BAT54S wikitext text/x-wiki =CitrinSolar CS 1.3 VBus-Interface= Oliver hat die Schaltung für sein CitrinSolar CS 1.3 nachgebaut und stand vor einem Problem: Beim Anschließen hat er sich bei den Pins am Regler verzählt - anschließend kamen statt der knapp 9 V nur noch unter 1 V aus der VBus-Schnittstelle. Telegramme kamen zwar noch raus, aber halt außerhalb der Spec. Die Reglerreihe ist etwas moderner/anders aufgebaut was ich bis jetzt von Resol [[Resol - Zerlegt|gesehen]] habe - und weniger modular. Ein [[Resol 71005014 Schnittstellenadapter|71005014 Schnittstellenadapter]] ist dementsprechend nicht vorhanden. Messmittel und Wissen sind vorhanden, also: <pre> Ich habe gerade nochmal Messungen gemacht und weiß grad etwas mehr. Im Regler gibts einen Spannungsregler, der kanpp 10.2V generiert. Zwischen den VBUS Leitungen ist dann eine 8.1V Z Diode, die die Spannung auf dem Bus begrenzt. …Und an der Stelle hängts grad noch bei mir. Der 10.2V Regler läuft, aber an der Z-Diode ist an der V+ Leitung nur noch 0.1V. D.h. hier ist irgendwas dazwischen defekt… </pre> ein paar Tage später kam dann die Erfolgsmeldung: <pre> Die Anlage läuft wieder. Am VBUS war eine BAT54S auf dem VBUS- durch und hat den Bus auf GND kurzgeschlossen. Die ausgelötete Stelle war die BAT54S. Heute eingelötet, jetzt geht alles. Auch der Adapter, den ich auf Basis deiner Raspi Schaltung mit dem Optokoppler gebaut hab, läuft. </pre> <gallery> citrinsolar_cs_13_diode1.jpg | Ort der defekten BAT54S citrinsolar_cs_13_diode2.jpg | Detailaufnahme (Diode entfernt) </gallery> Nachdem die BAT54S zwei serielle Dioden mit Mittelabgriff enthält und zwei nebeneinander platziert sind, liegt der Gedanke nah, dass diese (mehr oder weniger) als ESD-Schutz und zum Ableiten von Überspannungen angedacht sind. Funktioniert so lange gut, wie kein "Bums" dahinter ist, der thermisch umgewandelt werden muss. Immerhin haben sie ihren Zweck weitestgehend erfüllt - der Rest der Schaltung hat keinen offensichtlichen Schaden genommen. Einen Überblick über den Regler gibt es im Artikel [[Resol - Zerlegt#CitrinSolar_CS_1.3|Resol - Zerlegt]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] [[Kategorie:Reparatur]] 32ab020612929713e9385fa351ca9cefca689434 1820 1819 2022-11-11T22:13:31Z Chris 2 wikitext text/x-wiki =CitrinSolar CS 1.3 VBus-Interface= Oliver hat die Schaltung für sein CitrinSolar CS 1.3 nachgebaut und stand vor einem Problem: Beim Anschließen hat er sich bei den Pins am Regler verzählt - anschließend kamen statt der knapp 9 V nur noch unter 1 V aus der VBus-Schnittstelle. Telegramme kamen zwar noch raus, aber halt außerhalb der Spec. Die Reglerreihe ist etwas moderner/anders aufgebaut was ich bis jetzt von Resol [[Resol - Zerlegt|gesehen]] habe - und weniger modular. Ein [[Resol 71005014 Schnittstellenadapter|71005014 Schnittstellenadapter]] ist dementsprechend nicht vorhanden. Messmittel und Wissen sind vorhanden, also: <pre> Ich habe gerade nochmal Messungen gemacht und weiß grad etwas mehr. Im Regler gibts einen Spannungsregler, der kanpp 10.2V generiert. Zwischen den VBUS Leitungen ist dann eine 8.1V Z Diode, die die Spannung auf dem Bus begrenzt. …Und an der Stelle hängts grad noch bei mir. Der 10.2V Regler läuft, aber an der Z-Diode ist an der V+ Leitung nur noch 0.1V. D.h. hier ist irgendwas dazwischen defekt… </pre> ein paar Tage später kam dann die Erfolgsmeldung: <pre> Die Anlage läuft wieder. Am VBUS war eine BAT54S auf dem VBUS- durch und hat den Bus auf GND kurzgeschlossen. Die ausgelötete Stelle war die BAT54S. Heute eingelötet, jetzt geht alles. Auch der Adapter, den ich auf Basis deiner Raspi Schaltung mit dem Optokoppler gebaut hab, läuft. </pre> <gallery> citrinsolar_cs_13_diode1.jpg | Ort der defekten BAT54S citrinsolar_cs_13_diode2.jpg | Detailaufnahme (Diode entfernt) </gallery> Nachdem die BAT54S zwei serielle Dioden mit Mittelabgriff enthält und zwei nebeneinander platziert sind liegt der Gedanke nah, dass diese (mehr oder weniger) als ESD-Schutz und zum Ableiten von Überspannungen angedacht sind. Funktioniert so lange gut, wie kein "Bums" dahinter ist, der thermisch umgewandelt werden muss. Immerhin haben sie ihren Zweck weitestgehend erfüllt - der Rest der Schaltung hat keinen offensichtlichen Schaden genommen. Einen Überblick über den Regler gibt es im Artikel [[Resol - Zerlegt#CitrinSolar_CS_1.3|Resol - Zerlegt]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] [[Kategorie:Reparatur]] 6d57fbe399e9d4e0f9664e978157e41a708d86ac Datei:Citrinsolar cs 13 diode1.jpg 6 807 1800 2022-11-10T21:28:11Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Citrinsolar cs 13 diode2.jpg 6 808 1801 2022-11-10T21:28:11Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Prozeda-Decoder 0 460 1804 1610 2022-11-10T21:30:17Z Chris 2 wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FT2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Einblick in den Regler= Ein Griff in die Zukunft - 11/2017: Im Rahmen der [[Pirozeda]]-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen: <gallery> sungo_sxlplus.JPG | SUNGO SXLplus von außen sungo_sxlplus_ctrl_top.jpg | Controllerboard vorne sungo_sxlplus_ctrl_bot.jpg | Controllerboard hinten sungo_sxlplus_pwr_top.jpg | Leistungsboard vorne sungo_sxlplus_pwr_bot.jpg | Leistungsboard hinten sungo_sxlplus_pwr_port.jpg | Anschluss des Datasticks sungo_sxlplus_pwr_switch.jpg | Schaltmodule </gallery> ==Controllerboard== Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte. Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war. Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt. Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt... ==Leistungsboard== So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen. Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter. Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder. Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können. =[[Prozeda-Decoder/Der Datenstick|Der Datenstick]]= Um den Hauptartikel schlanker zu halten und da sich der Exkurs über den Datenstick als Sackgasse herausgestellt hat, ist dieser Teil des Artikels auf die gleichnamige Unterseite ausgegliedert. (Klick auf die Überschrift) =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank, Hans und alle die beteiligt waren für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] [[Kategorie:Zerlegt]] e7179cfa11d32340167f03c0962fcd4615ef03b9 1814 1804 2022-11-11T22:01:29Z Chris 2 /* Displayanzeige */ Weitere Daten und Info zu Übertragungsfehlern hinzugefügt wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FT2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Einblick in den Regler= Ein Griff in die Zukunft - 11/2017: Im Rahmen der [[Pirozeda]]-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen: <gallery> sungo_sxlplus.JPG | SUNGO SXLplus von außen sungo_sxlplus_ctrl_top.jpg | Controllerboard vorne sungo_sxlplus_ctrl_bot.jpg | Controllerboard hinten sungo_sxlplus_pwr_top.jpg | Leistungsboard vorne sungo_sxlplus_pwr_bot.jpg | Leistungsboard hinten sungo_sxlplus_pwr_port.jpg | Anschluss des Datasticks sungo_sxlplus_pwr_switch.jpg | Schaltmodule </gallery> ==Controllerboard== Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte. Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war. Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt. Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt... ==Leistungsboard== So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen. Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter. Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder. Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können. =[[Prozeda-Decoder/Der Datenstick|Der Datenstick]]= Um den Hauptartikel schlanker zu halten und da sich der Exkurs über den Datenstick als Sackgasse herausgestellt hat, ist dieser Teil des Artikels auf die gleichnamige Unterseite ausgegliedert. (Klick auf die Überschrift) =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt für ein zusätzliches Display. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> (siehe unten) Das letzte Zeichen: siehe Prüfsumme ====Weitere Daten==== Die weiteren Daten haben sich mir leider nicht vollständig erschlossen, einige Bits und Bytes lassen sich folgenden Displayelementen zuordnen: {| class="wikitable" ! Offset || Bit 7 (0x80) || Bit 6 (0x40) || Bit 5 (0x20) || Bit 4 (0x10) || Bit 3 (0x08) || Bit 2 (0x04) || Bit 1 (0x02) || Bit 0 (0x01) |- | 0x26 || || || || || || || || Symbol Info |- | 0x27 || || || || || || || || ? |- | 0x28 || || || || Pumpe oben || Pumpe mitte || Pumpe unten || || |- | 0x29 || || || || || || || || |- | 0x2A || || || || || || || || Symbol Einstellungen |- | 0x2B || || || || || || || || Relais Rahmen |- | 0x2C || || || || Relais 5 || Relais 6 || Relais 1 || Relais 2 || |- | 0x2D || || || || || Relais 3 || Relais 4 || Relais 7 || |- | 0x2E || || || || Symbol Hand || || || || |- | 0x2F || || || || || || || || Symbol Fehler |- | 0x30 || || || || || || || || |- | 0x31 || || || || || || || || |- | 0x32 || || || || Symbol Sonderfkt. || || || || |- | 0x33 || || || || Symbol "OK?" || || || || |- | 0x34 || || || || ? || || || || |} Anmerkungen: * Bytes 0x35 bis 0x3E sind nicht in der Tabelle aufgeführt, da bei ihnen keine Veränderungen beobachtet wurden, diese stehen immer auf 0x00 * Die mit Fragezeichen markierten Bits veränderten sich in den Traces, konnten aber keinem Symbol Element auf dem Display zugeordnet werden * Relais 8 ist unsicher, da es bei Tests nicht angesteuert werden konnte ====Fehlerhafte Übertragung==== Die zweite und dritte Displayzeile scheint es bei manchen Reglern (z. B. den Ratiofresh200) einen Bug zu geben. Nach genauerer Untersuchung (abermals vielen Dank an Frank für die Unterstützung!) scheint der verwendete Speicher falsch gemappt zu sein, zumindest erscheinen Texte, die für die zweite Zeile bestimmt sind teilweise im Bereich der Dritten. Dies ist bei der Anzeige der primären Vorlauftemperatur gut zu sehen: <gallery> prozeda_rf200_prim_vorlauf_56.jpg | Messwert 56,9 °C prozeda_rf200_prim_vorlauf_57.jpg | Messwert 57,0 °C </gallery> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">50 72 69 6D 84 72 20 56 6F 72 6C 61 75 66</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">Prim„r Vorlauf</span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 32 31 20 05 2D 54 20</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3">&nbsp;21 .-T&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">35 37 20 37 34 20</span> <span class="hb4">01 01 18 00 00 01 08 00 00 00</span>&nbsp;&nbsp;<span class="hb3">57 74 </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 00 00 18 00 00 00 00 00 00 00 00 00 00</span> 68&nbsp;&nbsp;<span class="hb4">...............</span>h </code> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">50 72 69 6D 84 72 20 56 6F 72 6C 61 75 66</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">Prim„r Vorlauf</span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 32 31 20 05 2D 54 20</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3">&nbsp;21 .-T&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">35 36 20 37 34 20</span> <span class="hb4">01 01 18 00 00 01 08 00 00 00</span>&nbsp;&nbsp;<span class="hb3">56 74 </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 00 00 18 00 00 00 00 00 00 00 00 00 00</span> 67&nbsp;&nbsp;<span class="hb4">...............</span>g </code> Im zweiten Drittel der <span class="hb3">dritten Zeile</span> (ab Offset 0x1F) sieht man, dass die Messwerte aus der zweiten Zeile "hineingedrückt" wurden. Bei einem anderen Regler (kann leider nicht mehr sagen, welcher es war) werden die Daten für die beiden Zeilen korrekt übertragen. Eine Display-Nachricht sieht dann beispielsweise wie folgt aus: <code> 00000000&nbsp;&nbsp;<span class="hb1">20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Kollektor&nbsp;&nbsp;&nbsp;</span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">35 30 2E 35 01 43 20 20</span> <span class="hb3">20 34 36 20 05 2D 01 43</span>&nbsp;&nbsp;<span class="hb2">50.5.C&nbsp;&nbsp;</span><span class="hb3">&nbsp;46 .-.C</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">2D 06 20 35 30 20</span> <span class="hb4">01 01 18 00 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb3">-. 50 </span><span class="hb4">..........</span> <br /> 00000020&nbsp;&nbsp;<span class="hb4">00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span> F5&nbsp;&nbsp;<span class="hb4">...............</span>õ </code> ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank, Hans und alle die beteiligt waren für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] [[Kategorie:Zerlegt]] e57ac5c648ebe3974f9aa239d0180754d421687d 1815 1814 2022-11-11T22:02:30Z Chris 2 Änderung 1814 von [[Special:Contributions/Chris|Chris]] ([[User talk:Chris|Diskussion]]) rückgängig gemacht. wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FT2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Einblick in den Regler= Ein Griff in die Zukunft - 11/2017: Im Rahmen der [[Pirozeda]]-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen: <gallery> sungo_sxlplus.JPG | SUNGO SXLplus von außen sungo_sxlplus_ctrl_top.jpg | Controllerboard vorne sungo_sxlplus_ctrl_bot.jpg | Controllerboard hinten sungo_sxlplus_pwr_top.jpg | Leistungsboard vorne sungo_sxlplus_pwr_bot.jpg | Leistungsboard hinten sungo_sxlplus_pwr_port.jpg | Anschluss des Datasticks sungo_sxlplus_pwr_switch.jpg | Schaltmodule </gallery> ==Controllerboard== Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte. Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war. Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt. Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt... ==Leistungsboard== So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen. Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter. Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder. Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können. =[[Prozeda-Decoder/Der Datenstick|Der Datenstick]]= Um den Hauptartikel schlanker zu halten und da sich der Exkurs über den Datenstick als Sackgasse herausgestellt hat, ist dieser Teil des Artikels auf die gleichnamige Unterseite ausgegliedert. (Klick auf die Überschrift) =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt eines zusätzlichen Displays. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten vermutlich (!) dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> Die weiteren Daten haben sich mir leider nicht erschlossen, scheinen aber Parameter für die Anzeige zu sein. Zum Beispiel anzuzeigende Symbole oder das Mapping von Informationen wie der Uhrzeit (wie hier gezeigt), die nicht in der Nachricht übertragen wurde, aber auf dem Display zu sehen ist. Das letzte Zeichen: siehe Prüfsumme ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank, Hans und alle die beteiligt waren für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] [[Kategorie:Zerlegt]] e7179cfa11d32340167f03c0962fcd4615ef03b9 1816 1815 2022-11-11T22:03:23Z Chris 2 /* Displayanzeige */ Weitere Daten und Info zu Übertragungsfehlern hinzugefügt wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FT2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Einblick in den Regler= Ein Griff in die Zukunft - 11/2017: Im Rahmen der [[Pirozeda]]-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen: <gallery> sungo_sxlplus.JPG | SUNGO SXLplus von außen sungo_sxlplus_ctrl_top.jpg | Controllerboard vorne sungo_sxlplus_ctrl_bot.jpg | Controllerboard hinten sungo_sxlplus_pwr_top.jpg | Leistungsboard vorne sungo_sxlplus_pwr_bot.jpg | Leistungsboard hinten sungo_sxlplus_pwr_port.jpg | Anschluss des Datasticks sungo_sxlplus_pwr_switch.jpg | Schaltmodule </gallery> ==Controllerboard== Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte. Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war. Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt. Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt... ==Leistungsboard== So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen. Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter. Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder. Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können. =[[Prozeda-Decoder/Der Datenstick|Der Datenstick]]= Um den Hauptartikel schlanker zu halten und da sich der Exkurs über den Datenstick als Sackgasse herausgestellt hat, ist dieser Teil des Artikels auf die gleichnamige Unterseite ausgegliedert. (Klick auf die Überschrift) =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Displayanzeige=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt für ein zusätzliches Display. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> (siehe unten) Das letzte Zeichen: siehe Prüfsumme ====Weitere Daten==== Die weiteren Daten haben sich mir leider nicht vollständig erschlossen, einige Bits und Bytes lassen sich folgenden Displayelementen zuordnen: {| class="wikitable" ! Offset || Bit 7 (0x80) || Bit 6 (0x40) || Bit 5 (0x20) || Bit 4 (0x10) || Bit 3 (0x08) || Bit 2 (0x04) || Bit 1 (0x02) || Bit 0 (0x01) |- | 0x26 || || || || || || || || Symbol Info |- | 0x27 || || || || || || || || ? |- | 0x28 || || || || Pumpe oben || Pumpe mitte || Pumpe unten || || |- | 0x29 || || || || || || || || |- | 0x2A || || || || || || || || Symbol Einstellungen |- | 0x2B || || || || || || || || Relais Rahmen |- | 0x2C || || || || Relais 5 || Relais 6 || Relais 1 || Relais 2 || |- | 0x2D || || || || || Relais 3 || Relais 4 || Relais 7 || |- | 0x2E || || || || Symbol Hand || || || || |- | 0x2F || || || || || || || || Symbol Fehler |- | 0x30 || || || || || || || || |- | 0x31 || || || || || || || || |- | 0x32 || || || || Symbol Sonderfkt. || || || || |- | 0x33 || || || || Symbol "OK?" || || || || |- | 0x34 || || || || ? || || || || |} Anmerkungen: * Bytes 0x35 bis 0x3E sind nicht in der Tabelle aufgeführt, da bei ihnen keine Veränderungen beobachtet wurden, diese stehen immer auf 0x00 * Die mit Fragezeichen markierten Bits veränderten sich in den Traces, konnten aber keinem Symbol Element auf dem Display zugeordnet werden * Relais 8 ist unsicher, da es bei Tests nicht angesteuert werden konnte ====Fehlerhafte Übertragung==== Die zweite und dritte Displayzeile scheint es bei manchen Reglern (z. B. den Ratiofresh200) einen Bug zu geben. Nach genauerer Untersuchung (abermals vielen Dank an Frank für die Unterstützung!) scheint der verwendete Speicher falsch gemappt zu sein, zumindest erscheinen Texte, die für die zweite Zeile bestimmt sind teilweise im Bereich der Dritten. Dies ist bei der Anzeige der primären Vorlauftemperatur gut zu sehen: <gallery> prozeda_rf200_prim_vorlauf_56.jpg | Messwert 56,9 °C prozeda_rf200_prim_vorlauf_57.jpg | Messwert 57,0 °C </gallery> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">50 72 69 6D 84 72 20 56 6F 72 6C 61 75 66</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">Prim„r Vorlauf</span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 32 31 20 05 2D 54 20</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3">&nbsp;21 .-T&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">35 37 20 37 34 20</span> <span class="hb4">01 01 18 00 00 01 08 00 00 00</span>&nbsp;&nbsp;<span class="hb3">57 74 </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 00 00 18 00 00 00 00 00 00 00 00 00 00</span> 68&nbsp;&nbsp;<span class="hb4">...............</span>h </code> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">50 72 69 6D 84 72 20 56 6F 72 6C 61 75 66</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">Prim„r Vorlauf</span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 32 31 20 05 2D 54 20</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3">&nbsp;21 .-T&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">35 36 20 37 34 20</span> <span class="hb4">01 01 18 00 00 01 08 00 00 00</span>&nbsp;&nbsp;<span class="hb3">56 74 </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 00 00 18 00 00 00 00 00 00 00 00 00 00</span> 67&nbsp;&nbsp;<span class="hb4">...............</span>g </code> Im zweiten Drittel der <span class="hb3">dritten Zeile</span> (ab Offset 0x1F) sieht man, dass die Messwerte aus der zweiten Zeile "hineingedrückt" wurden. Bei einem anderen Regler (kann leider nicht mehr sagen, welcher es war) werden die Daten für die beiden Zeilen korrekt übertragen. Eine Display-Nachricht sieht dann beispielsweise wie folgt aus: <code> 00000000&nbsp;&nbsp;<span class="hb1">20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Kollektor&nbsp;&nbsp;&nbsp;</span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">35 30 2E 35 01 43 20 20</span> <span class="hb3">20 34 36 20 05 2D 01 43</span>&nbsp;&nbsp;<span class="hb2">50.5.C&nbsp;&nbsp;</span><span class="hb3">&nbsp;46 .-.C</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">2D 06 20 35 30 20</span> <span class="hb4">01 01 18 00 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb3">-. 50 </span><span class="hb4">..........</span> <br /> 00000020&nbsp;&nbsp;<span class="hb4">00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span> F5&nbsp;&nbsp;<span class="hb4">...............</span>õ </code> ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank, Hans und alle die beteiligt waren für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] [[Kategorie:Zerlegt]] befe326ce870b1d98555a7947d5492c1e47a87c7 1817 1816 2022-11-11T22:06:56Z Chris 2 /* Displayanzeige */ eher dämliche Überschrift korrigiert wikitext text/x-wiki [[Datei:Prozeda_regler.jpg|thumb|RATIOfresh 200 von Wagner Solar]] "Funktioniert das auch mit meiner Solaranlage?" ist eine immer wiederkehrende Frage, nachdem ich den Artikel zum [[VBus-Decoder]] veröffentlicht habe. "Vielleicht, aber wahrscheinlich eher nein", war die häufigste Antwort. So in etwa auch bei der E-Mail von Frank und seiner RATIOfresh 200 von Wagner & Co Solartechnik, die er an den PC bzw. einen Single Board Computer (wie den Raspberry Pi) anbinden möchte um sich das ewige Gerenne in den Keller und das Auslesen des Datenloggers zu sparen. Die anfängliche Vermutung, dass der Regler von Resol kommt verflog relativ schnell (Es gab wohl einen Wechsel der Plattform), tatsächlich handelt es sich um ein Gerät von Prozeda. Ein paar Mails später gab es einen Link auf ein [http://www.forum-raspberrypi.de/Thread-projekt-solar-data-logger Raspberry Pi-Forum] - bis auf einen toten Link waren die Informationen relativ karg, außer dass in dem Datastick, der zum Loggen der Betriebsdaten verwendet wird, ein AT45DB081D steckt und am PC ein FT2232 im GPIO-Mode verwendet wird und wie die Pinbelegung am Datastick (oder der Buchse am Regler?) ist. Leider ist die Diskussion versandet und es gab keine weiteren Informationen. Aber ich war am Haken ;-) =Einblick in den Regler= Ein Griff in die Zukunft - 11/2017: Im Rahmen der [[Pirozeda]]-Entwicklung hat mir Hans freundlicherweise seinen zweiten Prozeda-Regler zur Verfügung gestellt. Natürlich habe ich einen vorsichtigen Blick hinein geworfen: <gallery> sungo_sxlplus.JPG | SUNGO SXLplus von außen sungo_sxlplus_ctrl_top.jpg | Controllerboard vorne sungo_sxlplus_ctrl_bot.jpg | Controllerboard hinten sungo_sxlplus_pwr_top.jpg | Leistungsboard vorne sungo_sxlplus_pwr_bot.jpg | Leistungsboard hinten sungo_sxlplus_pwr_port.jpg | Anschluss des Datasticks sungo_sxlplus_pwr_switch.jpg | Schaltmodule </gallery> ==Controllerboard== Soweit so unspektakulär. Leider ist auf dem Controllerboard nicht zu sehen, welcher Mikrocontroller verwendet wird - dieser versteckt sich hinter dem Display, das ich aus verständlichen Gründen nicht auslöten wollte. Interessant ist, dass sich links oben ein kleiner nicht so richtig schöner Hotfix befindet: Zwischen den Beinchen von V25 wurde relativ knapp ein 0603-Widerstand eingelötet. Auf der Rückseite befindet sich ebenfalls ein Bauteil, das so wohl nicht geplant war. Abgesehen davon macht das Board einen relativ aufgeräumten Eindruck, auch wenn mir die unten die Massefläche nicht so gut gefällt und sie oben gänzlich fehlt. Auffällig ist der nicht weiter beschriebene Footprint über S3 (im unteren Bereich der Leiterkarte): Das sieht sehr nach einem Platzhalter für einen Mini-DIN-Stecker aus. Leider habe ich hier keine Messungen durchgeführt... ==Leistungsboard== So richtig gut gefällt mir das LEistungsboard ehrlich gesagt nicht. Die Isolationsabstände sind mir etwas knapp und die Schaltmodule selbst machen zwar einen guten Eindruck, aber die Integration ist nicht so richtig schön bzw. hätte ich Angst, dass sie bei einem Fall herunterbrechen. Die Schaltmodule bestehen aus einem MOC3063 und einem ST T1235-600G (12 A Triac) sowie ein bisschen Hühnerfutter. Daneben gibt es noch einen potenzialfreien Kontakt mit Relais von Finder. Die Buchse für den Datastick ist keine große Überraschung, bis auf dass ihr Schirm nicht verbunden ist. Für den Datastick sicher irrelevant, für das optionale Gateway wäre eine richtig geschirmte Leitung zumindest kein Nachteil. Neben den 3,3 V liegt an der Buchse auch direkt die Ausgangsspannung des Netzteil. Mir ist aufgrund des dämlich platzierten Aufklebers auf dem Trafos zwar kein offizielles Rating bekannt, aber mit der Versorgung sollte man zumindest ein bisschen Spaß haben können. =[[Prozeda-Decoder/Der Datenstick|Der Datenstick]]= Um den Hauptartikel schlanker zu halten und da sich der Exkurs über den Datenstick als Sackgasse herausgestellt hat, ist dieser Teil des Artikels auf die gleichnamige Unterseite ausgegliedert. (Klick auf die Überschrift) =Livedaten= Denn in etwa an der Stelle, hatte ich das Geräusch vom [http://freesound.org/people/kwahmah_02/sounds/269476/ Kratzen eines Plattenspielers im Kopf]. Eine Mail von Frank mit neuen Loggingdaten. Ich hab zwar schon zuvor welche im Saleae-Format bekommen, nun aber mit etwas höherer zeitlicher Auflösung und so schaute ich sie mir noch einmal etwas genauer an: <gallery> Datei:Prozeda_verdaechtig.png </gallery> Der Stick wurde etwa bei Sekunde 8 gesteckt. Abgesehen vom "Ping" an den (teilweise nicht vorhandenen) Stick ist da verdammt viel Gewackel auf SCK und MOSI, bei dem noch nicht einmal CS aktiv ist... Da wird doch wohl nicht... In Logic kann man den Enable (also CS) auch auf active high einstellen. So kommt zu Tage, was in der Zeit über den Bus geht, das nicht den Flash betrifft. Hier ein kleiner Auszug aus dem Block, der von ziemlich vielen 0xAA gefolgt wird (deswegen habe ich es mir vorher auch nicht genauer angesehen): <pre> Time [s],Packet ID,MOSI,MISO 1.013882583333333,0,0xAA,0x00 1.013947000000000,0,0x55,0x00 1.014011416666667,0,0x55,0x00 1.014075666666667,0,0xAA,0x00 1.014139750000000,0,0x02,0x00 1.014203916666667,0,0x00,0x00 1.015365916666667,0,0xAA,0x00 1.015494333333333,0,0xAA,0x00 ... </pre> Irgendwann geht die Umsetzung vollkommen in die Hose, nachdem - warum weiß vermutlich nur der Hersteller - ein 11-bit langes Datenwort gesendet ist: <gallery> Datei:Prozeda_11bit_wtf.png </gallery> Nach dem nächsten Zugriff auf den Flash funktioniert die Analyse zwar wieder (da die State Machine zurückgesetzt wird) aber bis dahin hat man Datenschrott. Nachdem man sich in Logic auch die Rohdaten exportieren lassen kann, gibt es keine Ausrede es nicht selbst besser zu machen. Also einen sehr einfachen SPI-Analyzer in C# geschrieben, der das Timing sowohl für die Byte-Trennung als auch Pakettrennung verwendet. Kommt eine steigende Flanke am Clock später als 8 µs nach der letzten Veränderung, wird ein neuer Datensatz begonnen. Ist die Zeitdifferenz größer als 150 µs, wird ein neues Paket begonnen. Dabei sind die zeitlichen Abstände sehr konservativ. Folgende Daten purzeln aus dem Programm: {| class="wikitable" ! Time || CS || Data |- | 0,00850 || 1 || AA 55 55 AA 02 00 |- | 0,00998 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,05851 || 1 || AA 55 55 AA 01 00 |- | 0,05939 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,20858 || 1 || AA 55 55 AA 02 00 |- | 0,21006 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,25859 || 1 || AA 55 55 AA 01 00 |- | 0,25946 || 1 || 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 20 20 20 20 20 20 20 20 20 20 2D 31 34 20 05 2D 54 20 20 33 20 32 37 20 01 01 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 |- | 0,40867 || 1 || AA 55 55 AA 02 00 |- | 0,41015 || 1 || AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |- | 0,41492 || 1 || 09 |} ==Nachrichtentypen== Nach genauerem Durchsehen der Daten lassen sich 6 verschiedene Nachrichtentypen erkennen: {| class="wikitable" ! Länge || Zyklus [ms] || Meldungstyp || Bezeichnung || Anmerkung |- | 1 || 474/531 || - || unbekannt || immer 0x09, immer 11 bit lang |- | 6 || n/a || - || Meldungstyp || Gibt an, welche Nachrichtentypen folgen |- | 33 || 201 || <code>02 00</code> || Remote Request (?) || alle Bytes 0xAA, vermutlich Lesen eines abgesetzten Bedienteils |- | 64 || 201 || <code>01 00</code> || Displayanzeige || ASCII, synchron zum Displayinhalt am Regler |- | 68 || 1005 || <code>03 00</code> || Messwerte || Gleiches Datenformat wie auf dem Datastick |- | 70 || 1005 || <code>03 01</code> || Kopfdaten || Spalteninformationen zu den Messwerten und Systeminfos |- | 260 || - || - || unbekannt || vermutlich Systemparameter |} Die Länge ist die Länge der verschiedenen Nachrichten. Der Meldungstyp der unterschiedlichen Nachrichten leitet sich aus der Nachricht Meldungstyp ab, die diese speziellen Nachrichten ankündigt. ===0x09=== Das 0x09 ist - wie bereits geschrieben - die Katze im Protokoll: Ist da, holt sich Aufmerksamkeit und wirft mutwillig Zeug auf den Boden, nur um die Welt brennen zu sehen. Oder bringt mit ihrer abweichenden Länge zumindest die State-Machine vom Hardware-SPI durcheinander. Sinn und Zweck hat sich mir noch nicht erschlossen. Selbst wenn man das Timing betrachtet, taugt sie relativ wenig. Sie kommt abwechselnd in Abständen von etwa 474 und 531 ms, zwei dieser Nachrichten haben also einen Zyklus von 1,005 Sekunden. Könnte also der Synchronisation dienen. Aber warum die komische Länge von 11 bit? ===Meldungstyp=== Diese Nachricht kündigt andere Nachrichten an. Die <span class="hb1">letzten beiden Byte</span> geben - wie in der Tabelle oben vermerkt - den nächsten Meldungstyp an: <code> Offset(h) 00 01 02 03 04 05 <br /> 00000000&nbsp;&nbsp;AA 55 55 AA <span class="hb1">01 00</span>&nbsp;&nbsp;ªUUª<span class="hb1">..</span> </code> Das Timing ist bedingt durch die Natur der Nachricht nicht so richtig zyklisch, wobei sich natürlich eine Regelmäßigkeit erkennen lässt. ===Remote Request=== Auch wenn ich es nicht mit sicher sagen kann, handelt es sich hierbei mit großer Wahrscheinlichkeit um eine Abfrage eines abgesetzten Bedienteils. Auf eine andere Weise kann ich mir nicht erklären, warum nur 0xAA gesendet wird (was übrigens auch bei Lesevorgängen im Flash gesendet wird). Ein weiterer Fürsprecher ist, dass die Nachricht durchschnittlich nur 50 ms vor der Übertragung der Displayanzeige gesendet wird, was sehr für die Optimierung Aktion <> Reaktion spricht. Leider sind mir über die Inhalte keine näheren Informationen bekannt. ===Display=== Bei dieser Nachricht handelt es sich mit sehr großer Wahrscheinlichkeit um den Inhalt für ein zusätzliches Display. Nach den zwei Byte Kopfdaten kommen 36 ASCII-Zeichen. Da das Display am Regler 3 Zeilen mit 14 + 10 + 14 Zeichen hat, ist die Auftrennung der Daten dementsprechend. <!-- use colors they said, it will look great they said --> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 53 6F 6C 61 72 74 65</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3"> Solarte</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">63 68 6E 69 6B 20</span> <span class="hb4">01 00 00 00 01 00 00 00 10 00</span>&nbsp;&nbsp;<span class="hb3">chnik </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 10 00 00 00 00 00 00 00 00 00 00 00 00</span> 65&nbsp;&nbsp;<span class="hb4">...............</span>e </code> * <span class="hb1">Zeile 1 auf dem Display</span> * <span class="hb2">Zeile 2 auf dem Display</span> * <span class="hb3">Zeile 3 auf dem Display</span> * <span class="hb4">Weitere Daten</span> (siehe unten) Das letzte Zeichen: siehe Prüfsumme ====Weitere Daten==== Die weiteren Daten haben sich mir leider nicht vollständig erschlossen, einige Bits und Bytes lassen sich folgenden Displayelementen zuordnen: {| class="wikitable" ! Offset || Bit 7 (0x80) || Bit 6 (0x40) || Bit 5 (0x20) || Bit 4 (0x10) || Bit 3 (0x08) || Bit 2 (0x04) || Bit 1 (0x02) || Bit 0 (0x01) |- | 0x26 || || || || || || || || Symbol Info |- | 0x27 || || || || || || || || ? |- | 0x28 || || || || Pumpe oben || Pumpe mitte || Pumpe unten || || |- | 0x29 || || || || || || || || |- | 0x2A || || || || || || || || Symbol Einstellungen |- | 0x2B || || || || || || || || Relais Rahmen |- | 0x2C || || || || Relais 5 || Relais 6 || Relais 1 || Relais 2 || |- | 0x2D || || || || || Relais 3 || Relais 4 || Relais 7 || |- | 0x2E || || || || Symbol Hand || || || || |- | 0x2F || || || || || || || || Symbol Fehler |- | 0x30 || || || || || || || || |- | 0x31 || || || || || || || || |- | 0x32 || || || || Symbol Sonderfkt. || || || || |- | 0x33 || || || || Symbol "OK?" || || || || |- | 0x34 || || || || ? || || || || |} Anmerkungen: * Bytes 0x35 bis 0x3E sind nicht in der Tabelle aufgeführt, da bei ihnen keine Veränderungen beobachtet wurden, diese stehen immer auf 0x00 * Die mit Fragezeichen markierten Bits veränderten sich in den Traces, konnten aber keinem Symbol Element auf dem Display zugeordnet werden * Relais 8 ist unsicher, da es bei Tests nicht angesteuert werden konnte ====Fehlerhafte Übertragung==== Die zweite und dritte Displayzeile scheint es bei manchen Reglern (z. B. den Ratiofresh200) einen Bug zu geben. Nach genauerer Untersuchung (abermals vielen Dank an Frank für die Unterstützung!) scheint der verwendete Speicher falsch gemappt zu sein, zumindest erscheinen Texte, die für die zweite Zeile bestimmt sind teilweise im Bereich der Dritten. Dies ist bei der Anzeige der primären Vorlauftemperatur gut zu sehen: <gallery> prozeda_rf200_prim_vorlauf_56.jpg | Messwert 56,9 °C prozeda_rf200_prim_vorlauf_57.jpg | Messwert 57,0 °C </gallery> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">50 72 69 6D 84 72 20 56 6F 72 6C 61 75 66</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">Prim„r Vorlauf</span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 32 31 20 05 2D 54 20</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3">&nbsp;21 .-T&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">35 37 20 37 34 20</span> <span class="hb4">01 01 18 00 00 01 08 00 00 00</span>&nbsp;&nbsp;<span class="hb3">57 74 </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 00 00 18 00 00 00 00 00 00 00 00 00 00</span> 68&nbsp;&nbsp;<span class="hb4">...............</span>h </code> <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">50 72 69 6D 84 72 20 56 6F 72 6C 61 75 66</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">Prim„r Vorlauf</span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">20 20 20 20 20 20 20 20</span> <span class="hb3">20 32 31 20 05 2D 54 20</span>&nbsp;&nbsp;<span class="hb2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hb3">&nbsp;21 .-T&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">35 36 20 37 34 20</span> <span class="hb4">01 01 18 00 00 01 08 00 00 00</span>&nbsp;&nbsp;<span class="hb3">56 74 </span><span class="hb4">..........</span> <br /> 00000030&nbsp;&nbsp;<span class="hb4">00 00 00 00 18 00 00 00 00 00 00 00 00 00 00</span> 67&nbsp;&nbsp;<span class="hb4">...............</span>g </code> Im zweiten Drittel der <span class="hb3">dritten Zeile</span> (ab Offset 0x1F) sieht man, dass die Messwerte aus der zweiten Zeile "hineingedrückt" wurden. Bei einem anderen Regler (kann leider nicht mehr sagen, welcher es war) werden die Daten für die beiden Zeilen korrekt übertragen. Eine Display-Nachricht sieht dann beispielsweise wie folgt aus: <code> 00000000&nbsp;&nbsp;<span class="hb1">20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20</span> <span class="hb2">20 20</span>&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Kollektor&nbsp;&nbsp;&nbsp;</span><span class="hb2">&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">35 30 2E 35 01 43 20 20</span> <span class="hb3">20 34 36 20 05 2D 01 43</span>&nbsp;&nbsp;<span class="hb2">50.5.C&nbsp;&nbsp;</span><span class="hb3">&nbsp;46 .-.C</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">2D 06 20 35 30 20</span> <span class="hb4">01 01 18 00 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb3">-. 50 </span><span class="hb4">..........</span> <br /> 00000020&nbsp;&nbsp;<span class="hb4">00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span> F5&nbsp;&nbsp;<span class="hb4">...............</span>õ </code> ===Messwerte=== Die Messdaten sind nahezu identisch zu dem, was auf dem Datastick landet: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 00</span> <span class="hb2">6F 00 45 04 21 00 24 00 AD 01 D8 01 C4 09</span>&nbsp;&nbsp;<span class="hb1"> .</span><span class="hb2">o.E.!.$...Ø.Ä.</span> <br /> 00000010&nbsp;&nbsp;<span class="hb2">C4 09 C4 09 C4 09 45 02 40 01 C4 09 CD 01 00 00</span>&nbsp;&nbsp;<span class="hb2">Ä.Ä.Ä.E.@.Ä.Í...</span> <br /> 00000020&nbsp;&nbsp;<span class="hb2">00 00 00 00 00 00 00 55 55 10 00 00 00 00 00 00</span>&nbsp;&nbsp;<span class="hb2">.......UU.......</span> <br /> 00000030&nbsp;&nbsp;<span class="hb2">F8 08 00 00 01 00 01 00 01 00 02 00 00 00 F0 FF</span>&nbsp;&nbsp;<span class="hb2">ø.............ðÿ</span> <br /> 00000040&nbsp;&nbsp;<span class="hb2">00 00</span> <span class="hb3">20</span> C9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb2">..</span><span class="hb3"> </span>É </code> Die Daten werden durch die grün und gelb markierten Bytes eingeschlossen, die konstant zu sein scheinen. Das letzte Zeichen ist wieder die Prüfsumme. ===Kopfdaten=== Wie beim Logging auch werden Kopfdaten ausgegeben. Aufgrund der Gesamtlänge werden sie in kleinere Blöcke unterteilt und in diesen übertragen. <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">0D 11 04</span> <span class="hb2">00</span> <span class="hb3">20 20 20 20 44 61 74 75 6D 20 20 20</span>&nbsp;&nbsp;<span class="hb1">...</span><span class="hb2">.</span><span class="hb3">&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;</span> <br /> 00000010&nbsp;&nbsp;<span class="hb3">20 20 08 01 20 20 20 55 68 72 7A 65 69 74 20 20</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..&nbsp;&nbsp;&nbsp;Uhrzeit&nbsp;&nbsp;</span> <br /> 00000020&nbsp;&nbsp;<span class="hb3">20 20 09 02 20 53 65 6B 75 6E 64 65 6E 20 00 00</span>&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;.. Sekunden ..</span> <br /> 00000030&nbsp;&nbsp;<span class="hb3">00 00 10 03 20 20 4B 6F 6C 6C 65 6B 74 6F 72 20</span>&nbsp;&nbsp;<span class="hb3">....&nbsp;&nbsp;Kollektor&nbsp;</span> <br /> 00000040&nbsp;&nbsp;<span class="hb3">20 20 01 00</span> <span class="hb4">24</span> <span class="hb5">28</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb3">&nbsp;&nbsp;..</span><span class="hb4">&#36;</span><span class="hb5">(</span> </code> * <span class="hb1">Konstant</span> * <span class="hb2">Adresse</span> * <span class="hb3">Daten</span> * <span class="hb4">Trennzeichen</span> * <span class="hb5">Prüfsumme</span> Ich bin mir nicht ganz sicher, ob die Aufteilung Konstant/Adresse so korrekt ist, es wäre schon fast naheliegender, wenn die Aufteilung 2/2 Byte wäre. Allerdings habe ich keinen Anhaltspunkt dafür entdeckt. Die Adressen nach dem angegebenen Muster schlüsseln sich wie folgt auf: {| class="wikitable" ! Adresse || Bezeichnung |- | <code>0x00</code> || Spaltenbeschreibung 0 |- | <code>0x04</code> || Spaltenbeschreibung 1 |- | <code>0x04 * n</code> || Spaltenbeschreibung n |- | <code>0x20</code> || Spaltenbeschreibung 8 |- | <code>0xFA</code> || Systemdaten |} ====Spaltenbeschreibungen==== Fügt man die Daten aus den Nachrichten zusammen (hier: Adresse 0x00 und 0x04), erkennt man einen Unterschied zur Struktur im Flash: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;20 20 20 20 44 61 74 75 6D 20 20 20 20 20 <span class="hb1">08</span> <span class="hb2">01</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Datum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000010&nbsp;&nbsp;20 20 20 55 68 72 7A 65 69 74 20 20 20 20 <span class="hb1">09</span> <span class="hb2">02</span>&nbsp;&nbsp;&nbsp;&nbsp; Uhrzeit&nbsp;&nbsp;&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000020&nbsp;&nbsp;20 53 65 6B 75 6E 64 65 6E 20 00 00 00 00 <span class="hb1">10</span> <span class="hb2">03</span>&nbsp;&nbsp;&nbsp;Sekunden&nbsp;....<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000030&nbsp;&nbsp;20 20 4B 6F 6C 6C 65 6B 74 6F 72 20 20 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;&nbsp;Kollektor&nbsp;&nbsp; <span class="hb1">.</span><span class="hb2 hf2">.</span> <br /> 00000040&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B9 20 20 <span class="hb1">01</span> <span class="hb2">05</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ¹&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000050&nbsp;&nbsp;20 20 53 70 65 69 63 68 65 72 20 B3 20 20 <span class="hb1">01</span> <span class="hb2">06</span>&nbsp;&nbsp;&nbsp;&nbsp;Speicher ³&nbsp;&nbsp;<span class="hb1">.</span><span class="hb2">.</span> <br /> 00000060&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2">07</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2">.</span> <br /> 00000070&nbsp;&nbsp;20 52 FC 63 6B 6C 61 75 66 61 6E 68 2E 20 <span class="hb1">01</span> <span class="hb2 hf2">00</span>&nbsp;&nbsp;&nbsp;Rücklaufanh. <span class="hb1">.</span><span class="hb2 hf2">.</span> </code> Wo das vorletzte Byte jeder Spaltenbeschreibung <code>0x00</code> war, steht hier der <span class="hb1">Spaltentyp</span>. Dafür wird hier das <span class="hb2">letzte Byte</span> hochgezählt, wobei das letzte einer Nachricht immer <code class="hb2 hf2">0x00</code> ist. Trotzdem wird die Zählung in der nächsten Nachricht korrekt fortgesetzt. Bug oder Feature? ====Systemdaten==== Auch die Systemdaten sind etwas anders aufgebaut als im Datastick: <code> Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F <br /> 00000000&nbsp;&nbsp;<span class="hb1">20 20 57 61 67 6E 65 72 20 26 20 43 6F 20</span> 00 FB&nbsp;&nbsp;<span class="hb1">&nbsp;&nbsp;Wagner & Co </span>.û <br /> 00000010&nbsp;&nbsp;<span class="hb1">20 53 6F 6C 61 72 74 65 63 68 6E 69 6B 20</span> 00 FC&nbsp;&nbsp;<span class="hb1"> Solartechnik </span>.ü <br /> 00000020&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX XX XX XX XX</span> 00 00 00 00 00 FD&nbsp;&nbsp;<span class="hb2">XXXXXXXXXX</span>.....ý <br /> 00000030&nbsp;&nbsp;<span class="hb2">XX XX XX XX XX XX</span> 00 <span class="hb3">XX XX</span> <span class="hb4">XX XX</span> 00 00 00 00 00&nbsp;&nbsp;<span class="hb2">XXXXXX</span>.<span class="hb3">XX</span><span class="hb4">XX</span>..... </code> * <span class="hb1">Systemname</span> * <span class="hb2">Seriennummer</span> * <span class="hb3">System-Nummer</span> * <span class="hb4">System-Version</span> Achtung: Im Gegensatz zum Datenstick sind hier System-Nummer und System-Version nicht Little-Endian, sondern Big-Endian. ===Systemparameter=== Um ehrlich zu sein: ich habe nicht die leiseste Ahnung was der der Inhalt der Nachricht auch nur bedeuten könnte. Da ich nicht ausschließen kann, dass Informationen darin sind, die die Anlage identifizieren könnten, möchte ich an dieser Stelle nicht näher darauf eingehen. ===Prüfsumme=== Am Ende einer jeder Nutzdaten-Nachricht (also alle außer Meldungstyp und der verrückten 0x09) befindet sich eine Prüfsumme. Diese lässt sich gut an den Nachrichten erkennen, deren Inhalte sich nur wenig ändern - das letzte Byte ist dabei immer anders. Da es sich nur um ein Byte handelt ging ich im ersten Momentan davon aus, dass es sich am ehesten um CRC-8 handelt. Also [http://reveng.sourceforge.net/ RevEng] heruntergeladen und aufgrund der Uhrzeit dann lieber doch noch einmal geschaut, ob es sich die Entwickler nicht doch einfacher gemacht haben. Schließlich haben [[ECL-Bus-Decoder#Pr.C3.BCfsumme|so manche]] eine Vorliebe, das mit der Summe wörtlich zu nehmen. Warum nicht mal JavaScript? <source lang="javascript"> var msg = "20 00 6F ... C9"; var bytes = msg.split(/ /); var sum = 0; for (var i = 0; i < bytes.length; i++) { bytes[i] = parseInt(bytes[i], 16); if (i < bytes.length - 1) { sum += bytes[i]; } } var csok = (sum & 255) == bytes[bytes.length - 1]; console.log('checksum is %sok', csok ? '' : 'not '); </source> Gleich beim ersten Schuss getroffen. Schön. Oder auch nicht - die Bytewerte zu summieren ist alles andere als sicher. Allerdings muss man auch eingestehen, dass CRC-8 und CRC-16 bei den Datenlängen auch nicht mehr zur zuverlässigen Fehlererkennung taugt. ==Angezapft== Ok, jetzt wissen wir, wie die Daten aufgebaut sind. Jetzt müssen sie nur noch extrahiert und umgesetzt werden. Um überhaupt Daten empfangen zu können, muss Slave Select auf Masse liegen (zumindest wenn die Daten kommen) - sonst ist das SPI-Modul inaktiv. Leider stellte sich heraus, dass der Regler für den "zweiten Kanal" keinen Chip select herausführt. Das hätte die Sache etwas vereinfacht. Nun kann man einfach den Pin mit GND verbinden und bekommt die komplette Buskommunikation mit oder man invertiert das Signal - im einfachsten Fall mit einem Transistor - und hat schon mal die komplette Kommunikation zum Datenstick gefiltert (sofern man ihn überhaupt noch verwenden will). Aufgrund des verrückten 0x09 muss das SPI-Modul im laufenden Betrieb zurückgesetzt werden. Am besten funktioniert das über das Timing der Nachrichten. Der kleinste Abstand den ich in den Traces zwischen ihnen gesehen habe, war um die 600 µs. Der zeitliche Abstand zwischen den Bytes immer unter 100 µs, Ticks um die 100 bis 250 µs würden also vollkommen reichen, um Nachrichten sauber unterscheiden zu können. Zuerst habe ich mir überlegt, eine Statemachine zu verwenden, aber das ist gar nicht nötig, da es im Endeffekt nur zwei Zustände gibt: Es werden Daten empfangen und der Empfang ist abgeschlossen. Als Schnittstelle zum restlichen Programm dienen drei Methoden: * prozeda_rxData * prozeda_tick * prozeda_task <code>prozeda_rxData</code> muss durch den SPI-Received-Interrupt mit den empfangenen Daten als Parameter aufgerufen werden. In der Methode wird das empfangene Byte in den Puffer geschrieben und der Ticks-Zähler zurückgesetzt. <code>prozeda_tick</code> erwartet einen Aufruf alle ca. 100 µs. Ein bisschen mehr oder weniger ist nicht schlimm, evtl. muss <code>PROZEDA_MSG_MAXTICKS</code> angepasst werden. Die Konstante sollte nicht kleiner als 3 werden und die dadurch eingefasste Zeit nicht zu nah am die knapp 600 µs kommen, da sonst die empfangenen Daten überschrieben werden. Im Kern überprüft die Methode, wie lange das letzte empfangene Byte her ist. Wurde etwas empfangen und die zeitliche Bedingung erfüllt, wird das Flag <code>prozeda_process</code> gesetzt und damit <code>prozeda_task</code> zur Ausführung freigegeben. <code>prozeda_task</code> ist relativ unkritisch, sollte aber so regelmäßig ausgeführt werden dass es zwischen dem letzten <code>prozeda_tick</code> und dem nächsten <code>prozeda_rxData</code> noch vollständig durchläuft. Falls es in der Anwendung nicht reicht, kann ein doppelter Puffer helfen, der die Daten in <code>prozeda_tick</code> wegkopiert bevor sie von <code>prozeda_rxData</code> überschrieben werden können. ===Hardware=== {{Infobox AVR | Typ = AtMega328P | Takt = 12 | FuseH = 0xD9 | FuseL = 0xCE | FuseE = 0xFF }} Die Hardware ist relativ einfach: Der Atmega, sein Oszillator und der FET zum Invertieren des Chip Select. Dazu noch ein Angstwiderstände und fertig ist der Lack. Etwas schöner wäre natürlich nur noch eine passende Mini-DIN-Buchse. <gallery> Prozeda_sch.png|Minimalschaltung zum Empfang der Daten </gallery> ===Timing=== Um herauszufinden, wie viel CPU-Last der Empfang und das Auswerten des Protokolls benötigt und was man sonst noch machen kann, ist es unabdingbar, das Timing zu messen. Nun kann man anhand des Listings und der Befehlstabelle Zyklen zählen oder messen. Das geht mit einem Oszilloskop oder Logic Analyzer relativ einfach, indem man im Mikrocontroller am Anfang und Ende eines Funktionsaufrufs einen IO-Pin ein- bzw. ausschaltet. Über den Duty-Cycle kann man dann die CPU-Last messen, sollte den Wert aber trotzdem mit etwas Vorsicht genießen, denn: Schaltet man den IO innerhalb einer Funktion, misst man nicht den Overhead für den Sprung in und aus derselben. Zum Beispiel fallen beim <code>TIMER0_COMOA_vect</code> beim Eintritt 4 push-Befehle, ein in- und ein eor-Befehl an. Plus dem Setzen des Pins: 12 Zyklen. Beim Austritt 4x pop, je einmal out und reti und cbi: 15 Zyklen. Bei 12 MHz CPU-Takt bleiben also ca. 2,25 µs "ungesehen". An ungeeigneter Stelle kann das unangenehm werden. Folgende Zeiten habe ich mit dem Logic Analyzer gemessen - die Zeiten sind Mittelwerte aus 10 Messungen, der LA lief mit 32 MHz, also ist die zeitliche Auflösung 0,03125 µs {| class="wikitable" ! Methode || Bezeichnung || Dauer [µs] |- | prozeda_tick || keine Kommunikation || 0,588 |- | prozeda_tick || während Kommunikation || 1,338 |- | prozeda_tick || 4 Zyklen nach Kommunikation || 1,844 |- | prozeda_rxData || - || 1,419 |- | prozeda_process || nach MsgType-Nachricht || 8,918 |- | prozeda_process || nach Paket != Logdata || 2,339 |- | prozeda_process || nach 0x09 || 2,339 |- | prozeda_process || nach Logdata || 110,75 |} Die ganzen Werte sind ohne die oben erwähnten Ein- und Aussprungsszeiten. Über Duty-Cycle-Messungen kann man prinzipiell auch die CPU-Load für die einzelnen Aufgaben ermitteln. Hier im Durchschnitt über ca. 20 Sekunden und wieder ohne den Overhead: {| class="wikitable" ! Methode || CPU-Zeit [%] |- | prozeda_tick || 0,968 |- | prozeda_rxData || 0,025 |- | prozeda_process || 0,101 |} Erstaunlicherweise erzeugt der Tick am meisten Auslastung und wäre damit der erste Kandidat für Optimierung. ===Implementierungsstatus=== Aktuell Werden lediglich die MsgType-Nachrichten und die Logdaten ausgewertet. Aufgrund mangelnder Erkenntnis werden die Displaydaten nicht verarbeitet. Bei den Spaltendaten ist der Aufbau zwar bekannt, da sie für den aktuellen Regler aber keine zusätzliche Verwendung finden, habe ich es ausgelassen (die Definition - enum und typedef struct - existieren allerdings schon). Auch die 260-Byte lange Nachricht wird nicht untersucht, was aber noch interessant wäre. Ein weiterer Punkt wäre die Untersuchung des Rückkanals, um den Regler fernsteuern zu können. Besonders in Hinblick auf Fernwartung hätte dies einen größeren Reiz. Im Vordergrund stand in diesem Artikel allerdings das Auslesen der Messwerte. ===Programmbeispiel=== Im Download befindet sich ein Programmbeispiel, das gegen die Kommunikation des RATIOfresh 200 getestet wurde. Nach dem Empfang werden die Logdaten (Datum/Uhrzeit, Temperaturen, Ausgänge, Funktionen und Zapfung) als Text mit 115200 Baud 8N1 am UART ausgegeben. Neben der Ausgabe als "normalem" Text können die Daten auch im JSON-Format ausgegeben werden. Für die Anbindung an den Raspberry Pi, oder andere Embedded Systems wäre auch ein I²C-Slave sehr praktisch (Vielleicht, wenn ich lustig bin...). Ebenso eine Portierung auf einen physisch kleineren Mikrocontroller. =Anmerkungen= * Vielen Dank an Frank, Hans und alle die beteiligt waren für die vielen Infos, Daten, Fotos und Geduld! * Vielen Dank an das Forum von mikrocontroller.net und im speziellen Rainer B. * Für die Stimulation des Mikrocontrollers wurde sowohl ein anderer Mikrocontroller als auch ein zweiter Logic(-Nachbau) missbraucht. Besonders letzteres funktioniert erstaunlich gut. * Es gibt nun eine Implementierung für den Raspberry Pi: [[Pirozeda]] =Downloads= [[Datei:Prozeda-Decoder.zip]] enthält: * Hexdump eines Flashimages * Excel-Datei zur Auswertung eines Logging-Eintrags + Datenbeschreibung * Atmel Studio-Projekt zur Emulation des Datasticks * Atmel Studio-Projekt mit dem Reader der Livedaten [[Kategorie:AVR]] [[Kategorie:Protokoll]] [[Kategorie:Reverse Engineering]] [[Kategorie:Solar-Anlage]] [[Kategorie:Pirozeda]] [[Kategorie:Zerlegt]] 0fa172517cb24b3e9ec8a1b48025178efac461f2 Ikea Trådfri 0 566 1805 1292 2022-11-10T21:30:45Z Chris 2 wikitext text/x-wiki Trådfri, wie es aussieht kein richtiges [https://sv.wiktionary.org/wiki/Tr%C3%A5dfri schwedisches Wort], das für das drahtlose Beleuchtungssystem von Ikea steht. Da ich mittlerweile ein paar Lampen aus dem Möbelhaus bei mir im Einsatz habe, wollte ich mich ein wenig damit auseinandersetzen Anmerkung: Einige Teile des Artikels sind aus dem [//hobbyelektronik.org/b/2018/05/teardown-von-tradfri/ Blog übernommen] =Kabelloser Dimmer 003.478.31= [[Datei:tradfri_dimmer.jpg|thumb|Tradfri Dimmer, nahezu unsichtbar auf weißem Grund]] ==Teardown== Nimmt man das "User-servicable" Gehäuse vom Dimmer ab, bekommt man folgendes zu Gesicht: <gallery> tradfri_dimmer_assy_back2.jpg|Dimmer, innen von hinten tradfri_dimmer_assy_front.jpg|Dimmer, innen von vorne </gallery> Die Typenbezeichnung ist also neben der Ikea-Nummer ICTC-G-1. Obwohl das Gehäuse den Anschein macht, als wäre es Ultraschall-verschweißt, ist es nur geklipst. "Built to a price", das Schweißen wäre ein zusätzlicher Produktionsschritt und die Spritzguss muss sowieso ran. Mit einem vorsichtig angesetztem Schraubendreher lassen sich die Gehäuseteile trennen und die Leiterkarte kommt zum Vorschein: <gallery> tradfri_dimmer_pcb_assy.jpg|Leiterkarte mit Batteriehalter tradfri_dimmer_assy_back.jpg|Mech. Batteriehalter und Taster </gallery> Das Rückteil ist weniger spektakulär – ein Magnet und eine Kontaktfeder für die Batterie. In der anderen Hälfte steckt die "Magie": <gallery> tradfri_dimmer_pcb_top.jpg|Bestückungsseite der Leiterkarte tradfri_dimmer_pcb_bot.jpg|Rückseite der Leiterkarte (gespiegelt) </gallery> Der Codename für das Leiterkärtchen ist allen Anschein nach "Nebula_1F". Ich bin kein Trekkie, aber ist das eine Anspielung auf eine Schiffsklasse? Halbwegs futuristisch ist die Bedienung immerhin… Hirn und Herz ist ein Silabs EFR32 MG1P132GI. Für ein Datenblatt sollte man den Suchbegriff auf "EFR32MG1" einschränken: "[https://www.silabs.com/products/wireless/mesh-networking/efr32mg-mighty-gecko-zigbee-thread-soc Mighty Gecko Mesh Networking Wireless SoCs for Zigbee and Thread]"-Produkt-Familie beim Hersteller. Leider hört es da auch schon fast auf. der IC rechts unten (mit der Aufschrift "I4BEB2 P10343") dürfte ein EEProm sein (nachdem der Gecko wohl keinen internen hat), bei den oberen beiden (Aufdruck "S2 636" und "628") dürfte es sich vermutlich um Magnetometer und Gyro handeln. Letzteres vermutlich eher links oben, da diese Komponenten meines Wissens etwas höhere Pulsstromaufnahmen (schließlich muss die Mikromechanik angeschubst werden) haben. Schön an den Geckos ist, dass man die Pins ziemlich komfortabel auf die gewünschten Funktionen routen kann, für’s Reverse Engineering ist das allerdings nicht so ganz schön. Wenn man die Leiterbahnen etwas verfolgt erkennt man, dass es die Leiterkarte mehr als 2 Lagen hat, halbwegs erstaunlich, bei der vergleichsweise geringen Komplexität. Bei der Leiterkartenproduktion wurde das aber wieder reingeholt: Die Leiterkarte ist gestanzt statt gefräst und das Material sieht eher billig als günstig aus. Immerhin sind die Kontakte vergoldet und es wurden einige Testpunkte spendiert – da wird sicher ein I²C dabei sein. ==Reverse Engineering== Mit ein bisschen Probing lässt sich der I²C der beiden ICs oben ermitteln. <gallery> tradfri_dimmer_rev_i2c.jpg|I²C des Dimmers </gallery> Sobald der Mikrocontroller mit Strom versorgt wird, wird auch fleißig kommuniziert - mit den Devices 0x19 und 0x6B (jeweils 7-Bit-Adressen). Die Initialisierung selbst gab zumindest mir keinen richtigen Aufschluss darüber, was das Bauteil auf Adresse 0x19 ist. Dreht man den Dimmer, sieht man allerdings recht schnell, wer auf 0x6B reagiert: <gallery> flat_cw_packet.png|Kommunikation mit dem Gyroskop </gallery> Wenig schreiben, viel Lesen - das muss ein Sensor sein. Mit ein wenig Scripting habe ich versucht, die Daten vom Logic auseinanderzupflücken (analyze_i2c.py und ein bisschen Excel). Ich habe noch nicht geprüft, ob das Script so funktioniert wie es beabsichtigt war, allerdings stehen die für die Drehung relevanten Daten in Register 0x3F: <gallery> tradfri_dimmer_rev_i22_flat_cw.png|Drehung in Uhrzeigersinn tradfri_dimmer_rev_i22_flat_ccw.png|Drehung gegen Uhrzeigersinn </gallery> Alle Aufzeichnungen (Init, Drehen in/gegen Uhrzeigersinn liegend und vertikal) zum Untersuchen und herumspielen gibt es natürlich zum herunterladen: [[Datei:tradfri_dimmer_rev_i2c_comm.zip]] Dominik hat sich die Mühe gemacht und das Layout genauer analysiert: <gallery> tradfri_dimmer_pinout_erf32mg1.png|Pinout des µC (aus dem [https://www.silabs.com/documents/public/data-sheets/efr32mg1-datasheet.pdf Datenblatt]) tradfri_dimmer_rev_pinmap.jpg|Pin-Assignment auf der Leiterkarte (Bild von Dominik) </gallery> =Fernbedienung 303.388.49= [[Datei:tradfri_remote.jpg|thumb|Tradfri Fernbedienung]] ==Teardown== Habe ich noch nicht selbst durchgeführt, aber [https://www.heise.de/make/artikel/Ikea-Tradfri-Anleitung-fuer-ein-ESP8266-Lampen-Gateway-3598411.html Heise]. Dominik, der sich auch etwas näher mit dem Zerlegen und Umbauen der Fernbedienung auseinandergesetzt hat, gab folgende Tipps: * Das Gummi auf der Rückseite an zwei Stellen (45° versetzt/viertel Kreis) bis aufs Plastik drunter einschneiden (Teppichmesser) * Das Gummi abziehen (kleine Zange und wenn verfügbar ein bisschen Heißluft) * Dann schneide/reiße ich mich von der Batterie aus nach Außen (kleine Zange/Seitenschneider) * Ist erst einmal ein Schlitz da, ploppt der vordere Teil heraus (mit etwas biegen und drück) * Das mit dem Dremel war mir bis jetzt zu gefährlich, am Ende ist dann nur das PCB hin und der Dremel voller geschmolzenem Plastik ==Wandhalterung für Unterputz-Dosen== Dominik war es auch, der ein 3D-Design erstellt hat, mit dem man die Fernbedienung in die gleiche Form wie Jäger/Busch-Schalter zu bringen. Da er selbst keine Homepage/Blog hat, bat er mich, sein Design zur Verfügung zu stellen: <gallery> tradfri_remote_jaeger_render.png|Rendering der Frontplatte tradfri_remote_jaeger.jpg|Foto des Druckteils (Bild von Dominik) </gallery> Vielen Dank dafür! Da ich selbst unerfahren in Sachen 3D-Druck bin, kann ich die Daten leider nur as-is weitergeben. Alle Rechte bleiben bei Dominik (Kontakt kann ich in beidseitigem Einverständnis vermitteln). Unter Vorbehalt ist die kommerzielle Nutzung ausgeschlossen. [[Datei:tradfri_remote_frontplate.zip|Download]] =GU10-Lampe 803.652.70= ==Teardown== Zu dem Zeitpunkt, als ich die GU10-Lampe gekauft habe, war sie mit IIRC knapp 7 Euro diegünstigste verfügbare Lampe mit Funk. Mittlerweile (02/2019) hat sich der Preis mit 13 Euro fast verdoppelt. Ob sie anfangs unter Preis verkauft wurde, möchte ich nicht beschwören. Frisch as der Packung sieht sie wie folgt aus: <gallery> tradfri_gu10_back.jpg|von hinten tradfri_gu10_front.jpg|das "aktive" Ende </gallery> Der Deckel bzw. die Optik lässt sich mit einem flachen Schraubendreher erstaunlich leicht entfernen, innen ist das Teil auf ersten Blick eher unspektakulär: <gallery> tradfri_gu10_front_open.jpg|Entfernte Optik tradfri_gu10_heatsink.jpg|ohne LED-Leiterkarte </gallery> Ein herumflatterndes Kupferfähnchen? Sieht nach einem late fix zum Bestehen der EMV-Prüfungen aus. Das LED-Modul hat keine Wärmeleitpaste im Rücken und die leicht verklebte Metallplatte lässt sich mit sanfter Gewalt (mit dem Schraubendreher am Schraubloch hebeln) herausnehmen. Dahinter begrüßt einen die Elektronik – oder zumindest das Funkmodul. Es sieht besser aus als es ist. Ich bin mir nicht sicher, ob das Shielding seinen Namen verdient hat, es wackelt wie ein Kuhschwanz. Eine saubere elektromechanische Verbindung sieht auf jeden Fall anders aus. Ein bisschen mehr hebeln und das Innere erblickt das Tageslicht: <gallery> tradfri_gu10_module.jpg|Funkmodul mit Shielding und Fähnchen tradfri_gu10_module_open.jpg|...und entdeckelt </gallery> Das Silabs-Logo lässt sich erahnen, links unten sitzt auch ein "alter Bekannter". Bin mir ziemlich sicher, dass es sich hier um einen EEProm handelt. Im Bild sieht man auch, dass das Modul by design eher bescheiden eingelötet ist: unter der linken Kante sitzt ein SMD-Widerstand, unter der rechten nicht. Da man sowas maschinell nicht vernünftig gelötet bekommt: Mit ein bisschen Zug kommt auch das Netzteil + Controller raus. Es ist hinten nicht verlötet und sieht von oben zwar sehr eng gepackt aber dennoch halbwegs ok-ish aus: <gallery> tradfri_gu10_pcb_angle.jpg|Eng gepackter LED-Treiber </gallery> Von unten sollte man es – zumindest wenn man Elektroniker ist und einen schwachen Magen hat – besser nicht ansehen. Verdammt viele Handlötungen, mehr Lötzinn als mir lieb ist und noch mehr ekelhafte Flussmittelrückstände. Der 5-Beiner oben ist mit ZR7IB beschriftet (kein Datenblatt auffindbar). Das Bauteil im SO-8-Gehäuse heißt BEH7JB (auch nix zu finden). Die Qualität dieser Leiterkarte ist leider nicht wirklich rühmlich. Einen High-Pot-Test würde ich angesichts solcher Lötstellen nicht unbedingt machen: <gallery> tradfri_gu10_pcb_bot.jpg|LED-Treiber von unten tradfri_gu10_pcb_nohipot.jpg|Lötqualität des Treibers </gallery> ==Reverse Engineering== Die Beschaltung des Funkmoduls kann man anhand der Leiterkarte relativ einfach ermitteln: <gallery> tradfri_gu10_rf_module.jpg|Tradfri RF-Modul </gallery> Von in dieser Ansicht unten von links nach rechts: {| class="wikitable" ! Pin || Funktion |- | 1 || unbekannt |- | 1 || unbekannt |- | 1 || unbekannt |- | 1 || PWM Out |- | 1 || GND |- | 1 || 3,3 V |} Jemand anderes hat eine genauere Untersuchung durchgeführt und [https://tradfri.blogspot.com/2017/04/pinout-of-tradfri-zigbee-module.html alle Pins gemappt]. Was kommt raus? An den Logic Analyzer angeklemmt zeigt sich bei niedrigster Helligkeit eine On-Time von 94,92 µs und eine Frequenz von genau 600 Hz. Der Duty-Cycle ist also bei 5,695 %. Den Slider in der App auf etwa die Hälfte gezogen ergibt sich ein Duty-Cycle von ca. 24 %, bei dreiviertel sind es 50 % Duty-Cycle. Die Frequenz bleibt konstant. An dieser Stelle endet meine Untersuchung. Der Github-User [https://github.com/basilfx/TRADFRI-Hacking basilfx] ist da deutlich tiefer in Sachen Hacking eingestiegen. [[Kategorie:Hausautomatisierung]] [[Kategorie:Beleuchtung]] [[Kategorie:Zerlegt]] 80e099566765cbec51cb0b32b180faceb43c8529 Kühlung für Zhongdi ZD-939L 0 367 1806 1192 2022-11-10T21:34:18Z Chris 2 wikitext text/x-wiki Vor geraumer Zeit hab ich mir eine Zhondi ZD-939L auf den Basteltisch gestellt. Diese Heißluftlötstation ist gerade beim Entlöten von SMD-Bauteilen ein sehr nützlicher Helfer. [[Datei:ZD-939L Hinweis.JPG|thumb|Aufkleber als Workaround]] Eines hat mich allerdings vom ersten Tag weg gestört: sie hat keinen Nachlauf zum Kühlen des Heizelements. Als "Workaround" hat der Importeur lediglich einen Hinweis angebracht, dass man vor dem Abschalten auf die Mindesttemperatur herunterdrehen und eine Minute warten solle. Mit dem Warten kann ich leben, allerdings ist das Einstellen der Temperatur etwas nervig: Minus-Taster drücken und halten und sich für jedes Grad einen Pieps anhören. Nur um beim Nächsten Einschalten genau das Gegenteil zu machen. selbstverständlich ebenfalls mit akustischer Untermalung. Dabei gibt es die Heißluft-Station (neben der Version mit Nachlauf) auch mit dienen Schalter fürs Heizelement. Warum hat das meine nicht? Es wird höchste Zeit, dass sich das ändert. =Analyse= [[Datei:ZD-939L_Innenleben.jpg|thumb|Blick auf die hintere Leiterkarte]] Auf das Ding und reingeschaut. Die Elektronik ist auf 3 Leiterkarten verteilt - hinten befindet sich ein teilbestücktes Board auf das die Netzleitung führt. Nachdem sich nichts darauf befindet, das auf Regelung hindeutet, dürfte es der Leistungsteil sein. Vorne im Gehäuse findet sich neben der Leiterkarte mit den Tastern vom Frontpanel auch die Platine mit dem Display. Die 3 schwarzen Vielbeiner darauf lassen erahnen: hier wird höchstwahrscheinlich geregelt. Heizung abdrehen könnte man nun sowohl auf der Leistungs- als auch der mutmaßlichen Reglerplatine. Man könnte natürlich auch direkt in die Leitung zum Heizelement eingreifen - aber warum sich die Finger an 230 V verbrennen, wenn man es auch einfacher und sicher haben kann? Ein genauerer Blick auf die Display-Platine kann also nicht schaden: <gallery> Datei:ZD-939L Regler.JPG|Die Reglerplatine </gallery> Der 8-beinige Chip links ist ein LM358, also ein Operationsverstärker. Beim mittleren Chip im TQFP-Gehäuse handelt es sich um einen Silabs C8051F310 - einem Mikrocontroller. Rechts im Bild befindet sich ein Holtek HT1621B. Holtek kennt man auch als Mikrocontroller-Hersteller - aber zwei Mikrocontroller für einen einfachen Regler? Nicht ganz. Der Holtek ist lediglich ein LCD-Controller, was auch die Leiterbahnen zu ihm erklärt. Die Regelung übernimmt alleinig der Silabs-Chip. Interessanter als die Regelung und das Display ist für den Umbau, über welche Anschlüsse die Heizung angesteuert wird. Drei der vier Stiftleisten sind mit der Platine hinten verbunden. Die 4-polige Stiftleiste links im Bild führt zur Taster-Platine und fällt damit schon mal weg. Die untere zweipolige Stifleiste ist ein Kandidat - nachdem sie aber verdächtig nahe am LM358, ein paar diskreten Bauteilen und einem Poti liegt, dürfte es sich um den Anschluss für den Temperaturfühler sein. Alle Leitungen außer dieser verbunden bestätigt den Verdacht: Keine Temperaturanzeige. Bleiben nur noch zwei. Die links obere sieht verdächtig nach Stromversorgung aus: etwas dickere Leiterbahnen, Dioden und Kondensatoren. Nicht zuletzt ein 78L05. Warum aber 3 Pins? Eingangsspannung, Masse und Ausgangsspannung? Nein, vermutlich handelt es sich um eine symmetrische Versorgung - entweder fürs Display oder den Operationsverstärker. Ein Blick in den hinteren Teil der Lötstation bestätigt es: Ein Trafo mit Mittelabzapfung. Die Heizung muss also von der Stiftleiste rechts oben angesteuert werden. Am Stecker hängen zwei Drähte, was die Sache leichter macht. Masse lässt sich durchpiepsen und damit ist auch der Ausgang gefunden. Muss nur noch geklärt werden, wann welche Spannung anliegt und ob man einfach so einen Schalter einbringen kann. Multimeter angehängt und den Aparillo losbrummen lassen: 5V, wenn die Heizung an ist. Um sicherzustellen, dass die 5V berührungssicher sind, schnell gegen das Gehäuse, das mit PE verbunden ist: 0V, also galvanisch getrennt. Ausgezeichnet! =Umbau= Ein Ort für den zusätzlichen Schalter ist schnell gefunden: Neben dem Hauptschalter ist noch Platz. Der Akkuschrauber leiert ein Loch in die Platte und der Schalter ist drin. Für die elektrische Verbindung habe ich die Leitung zum "Backpanel" aufgetrennt und den Schalter einfach eingefügt. Da ich die Schaltung dahinter nicht genauer ansehen wollte, habe ich mich für die sicherere Ansteuerung entschlossen - theoretisch könnte man einfach eine der Leitungen auftrennen und den Schalter einfügen. Allerdings bekommt dann die Schaltung "hinten" entweder das Signal vom Mikrocontroller oder floatet durch die Gegend. Da das nicht besonders toll ist, wechselt der Schalter zwischen dem ursprünglichen Pfad und Masse. So gibt es immer einen definierten Pegel und Probleme werden bestmöglich ausgeschlossen. <gallery> Datei:ZD-939L Elektronik vorne.JPG|Umgebaute Elektronik </gallery> Der erste Test im noch auseinander gebauten Zustand spricht für Erfolg: die Soll-Temperatur ist bei 160 °C, die Ist-Temperatur bleibt bei 25 °C. Nach Kippen des Schalters klettert die Anzeige wie vorher nach oben. <gallery> Datei:ZD-939L Front umgebaut.JPG|Funktionstest mit ausgeschalteter Heizung </gallery> =J-EXT= Auf dem Board befinden sich noch zwei Vorhalte für Stiftleisten. Eine unbeschriftete (vermutlich zum Download der Firmware) und eine namens J-EXT. Rein aus Neugierde habe ich mir letztere etwas genauer angesehen, vielleicht spricht das Board ja mit einem. Die Leiterbahnen führen schon einmal alle zum Mikrocontroller, zusammen mit dessen Datenblatt lassen sich die Pins zuordnen. P3.x haben leider keine spezielle Peripherie zugeordnet, also eher unwahrscheinlich, dass da UART rauskommt. Möglich ist aber alles. Also Spannung mit dem Scope nachgemessen und nach positivem Befund den Logic-Analyzer angeschlossen: [[Datei:ZD-939L_Logic-Analyzer.png]] Aus den Daten lässt sich folgende Zuordnung ableiten: {| class="wikitable" |- ! Pin J-EXT !! Pin µC !! Pin-Name !! Funktion |- | 1 || - || - || +5V |- | 2 || 7 || P3.1 || ? |- | 3 || 9 || P3.3 || Clock |- | 4 || 10 || P3.4 || Data |- | 5 || - || - || GND |} Ein "Datenpaket" dauert etwa 2,6 ms und wird alle 20 ms gesendet. Allem Anschein nach werden die Daten in 16-Bit-Gruppen geschickt, zumindest bleibt der Clock nach 16 Bits immer ein bisschen länger High. Die Daten habe ich nicht genauer untersucht, da für mich der Reiz einfach nicht da ist. Wer es versuchen will, kann sein Glück mit meiner Aufzeichnung versuchen: [[Datei:ZD-939L J-EXT.zip]] Die Daten wurden mit Saleae Logic 1.1.18 Beta erstellt. Wenn ich mich richtig erinnere, war die Temperatur auf 160 °C Soll eingestellt und eine Ist-Temperatur von 25 °C (weniger macht das Teil anscheinend nicht) angezeigt. =Nachtrag 19.04.2015= Manfred hat sich etwas mehr Arbeit gemacht und und der Station zusätzlich noch eine Status-LED und eine niedrigere Stufe für den Luftdurchsatz hinzugefügt. Hier seine Beschreibung - vielen Dank dafür! <code> Jetzt habe ich endlich mal meine Heißluftstation bearbeitet. Etwas ange****t bin ich ja, dass da tatsächlich direkt mit Netzspannung geheizt wird, hätte ich nicht erwartet. Eigentlich kann da ein passender Schalter rein und fertig - aber, um das ordentlich zu machen, müsste ich die Kiste zerlegen, wegen Feilspänen, da habe ich keine Lust zu. Ich habe Deinen Vorschlag gegriffen und trenne die Steuerleitung. Gegen die Langeweile noch eine LED rein, weiße sieht man unter 1 mA schon leuchten. Im Gegensatz zur Beschreibung stehen da keine 5 V an der Steuerleitung, ich messe knapp 3,2 Volt. Wenn die leuchtet, ist also Abkühlphase! Die Luftmenge ist mir zu hoch, auah, am Drehpoti liegt Netzspannung. Das Ding hat 470 kOhm, mal einen R in Reihe probieren, bis gut 650 k liefert meine Pumpe noch Luft. Da ist jetzt ein weiterer Schalter drin, der 220 k in Reihe legt - eigentlich wäre auch ein 1 Meg-Poti mit parallel 2 MOhm klug, wenn es denn im Vorrat gewesen wäre. Vielleicht sollte dieser Punkt im Wiki ergänzt werden? Ich habe Kippschalter MTA-106 von Knitter eingesetzt, die können 250 Volt, haben aber keine VDE-Zertifizierung - von daher bin ich an der Stelle nicht ganz sauber. [...] Wie man sieht, sieht man an den Kippschaltern keine Mutter, Bastelei darf gerne auch anständig aussehen. Die Schalter haben Feingewinde, der Stahl vom Chinesengehäuse ist gut, also habe ich Gewinde geschnitten und von hinten gekontert. </code> <gallery> Datei:ZD-939L M Stromlauf_grau_1200.png|Stromlaufplan der Änderung Datei:ZD-939L M Detail_Schalter_1600_60.jpg|Änderungen von innen Datei:ZD-939L M Schalterfeld_1200_60.jpg|...und von vorne </gallery> = Nachtrag 26.05.2015 = Mittlerweile gibt es beim Ramschmax auch eine Version mit [http://www.pollin.de/shop/dt/MjM4OTUxOTk-/Werkstatt/Loettechnik/Loetgeraete/Heissluft_Loetstation_mit_LCD_ZD_939L_4_Wechselduesen.html fertig eingebautem Kühlschalter]. =Siehe auch= * [http://hobbyelektronik.org/b/2014/05/eine-kleine-anmerkung-zu-chinesischen-namen/ Eine kleine Anmerkung zu chinesischen Namen] [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] [[Kategorie:Zerlegt]] 7f291a1c3d3b43992d0e87e46fba6875b62e31f3 Tchibo Wetterstation 0 299 1807 1759 2022-11-10T21:35:26Z Chris 2 wikitext text/x-wiki [[Datei:TCM_vorne.jpg|thumb|Tchibo Wetterstation]] Letztes Jahr gab es von meiner Schwester eine Funk-Wetterstation (TCM 279340) zu Weihnachten. Ich hatte zwar schon eine etwa gleichwertige, aber man will sich Neuerungen natürlich nicht querstellen. Interessant an dem Teil war auf dem ersten Blick das Farbdisplay, das sich nach näherer Betrachtung als Farbfolie auf einem Schwarz-Weiß-LCD herausstellte. Diese Effekthascherei sieht ehrlich gesagt nicht einmal allzu schlecht aus, obwohl sie durch den massiv niedrigeren Kontrast eigentlich nur Nachteile bringt. Aber bekanntlich zählen ja die inneren Werte; und die sind trotz der Preisklasse (und der angesetzten Zielgruppe) nicht allzu schlecht. Aufgrund von Prüfungsvorbereitungen blieb das Teil relativ lange unbehelligt, bis mich endgültig die Neugierige weckte: =Hardware= Die Wetterstation selbst ist mit Thermo- und Hygrometer, sowie einem Barometer ausgestattet, dass auf dem Display lediglich eine Tendenz anzeigt. Neben dem 433MHz-Empfänger ist zugleich ein Zeitzeichenempfänger (DCF77) verbaut, der kein Meteotime empfängt. Da war wohl die Lizenz teurer als das Barometer ;-) Im "Außenfühler" sitzt wiederum ein Thermo- und Hygrometer. Neben Kanalwahlschalter und Tx-Knopf war's das auch schon wieder. Ok, Batterien frisst das Teil auch noch. <gallery> Datei:TCM_innen.jpg|Verbasteltes Innenleben der Wetterstation Datei:TCM_sender.jpg|Außensensor/Sender </gallery> Wie beim [[EMR7370]]: Am Anfang war der Schraubendreher. Das Innenleben der Station ist relativ modular aufgebaut. Jeweils eine eigene Platine für DCF77, 433MHz, Barometer und Hygrometer. Auf der Hauptplatine ist dann der Rest. Dadurch war es mehr als einfach, das Signal der Begierde abzufangen. Wenn man schon mal drin ist, habe ich mir auch gleich die Datenleitungen des Barometers herausgeschleift - man weiß ja nie. =Protokoll= Im zweiten Schritt kommt der Logic Analyzer ins Spiel: [[Datei:TCM_17.7degC78%.png|thumb|800px|left|Interessant bis ~130ms]] Wie man sieht, sind die Pulsweiten (low-Zeiten) nach jedem Flankenwechsel unterschiedlich - darin muss also die Information stecken. Um Muster besser zu erkennen schnappte ich mir die Daten, importierte sie in Excel und ließ sie mir visualisieren. Dazu habe ich einfach die Zeitdifferenzen zwischen den einzelnen Zeilen ausgeben lassen und das Ergebnis durch bedingte Formatierung hinterlegt. Zusätzlich habe ich alle "1-Zeiten" herausgefiltert, da dort augenscheinlich keine Informationen übertragen werden <gallery> Datei:TCM_Excel1.png|visualisierte Daten Datei:TCM_Excel2.png|gleiches noch einmal, nebeneinander </gallery> wie man im zweiten Bild deutlich sieht, gibt es Synchronisation und Daten. Dabei ist eine Pause (bzw. Sendepuls, so genau weiß ich es nicht) von 8,9ms das Synchronisationswort und knapp 2 bzw. 4ms eine 1 bzw. 0. Insgesamt werden die Daten 8 mal übertragen - ist zwar nicht gerade edel, aber es funktioniert. Das Wissen über Kanalkodierung, Codeverkettung und Faltungscodes ist bei den Herstellern von solchem Zeug wohl noch nicht angekommen. Hat immerhin den Vorteil, dass es Leute wie ich nicht zu schwer haben. Bleibt nur noch die Frage der Zuordnung. Was ist eine 1 und was eine 0 - und vor allem: wo steht was? Sicher ist zumindest, dass 36 Bit übertragen werden. ==Datenfarm== Nachdem ich über mehrere Abende hinweg sporadisch Werte aufzeichnete (und erzeugte) bekam ich schließlich knapp 50 Datensätze, die ausgewertet werden wollten. Um Copy & Paste-Orgien in Excel zu ersparen, bastelte ich mir ein kleines PHP-Script, das die Zeitstempel in Binärdaten umwandelt: <source lang="php"> function timing2data($filename) { $fh = fopen($filename, "r"); $lasttime = -1; $data = array(); while($line = fgets($fh)) { $time = explode(", ", $line); $time = floatval($time[0]); if($lasttime !== -1) { $val = round(($time - $lasttime) * 1000); switch($val) { case 9: echo "\n"; break; case 0: echo ""; break; case 2: echo "0"; break; case 4: echo "1"; break; default: echo "<".$val.">"; break; } } $lasttime = $time; } fclose($fh); } </source> Hier habe ich auch die Annahme getroffen, dass ein kurzer Puls 0 und ein langer 1 entspricht (ich sollte richtig liegen). Die Ausgabe sieht dann zum Beispiel wie folgt aus: <pre> 000001010000111001111111100100010000 0000010100001110011111<673><19> </pre> die Werte in den spitzen Klammern sind Pausenzeiten, die nicht als 1, 0 oder Sync erkannt wurden und somit Übertragungsfehler darstellen. Bei der Auswertung fanden sich dann auch einige Datensätze, bei denen die Auswertung nicht mehr allzu zuverlässig war - also gerade so zwei Übereinstimmungen in den Datenworten. Aber es hat gereicht. In Excel ging dann die Suche nach der Antwort los. ==Beispieldaten== {| class="wikitable sortable" |- ! Temperatur !! Luftfeuchtigkeit !! 0 !! 1 !! 2 !! 3 !! 4 !! 5 !! 6 !! 7 !! 8 |- | 24,1°C || 43% || 0000 || 0101 || 0010 || 1000 || 1111 || 0000 || 1100 || 0010 || 0101 |- | 24,6°C || 45% || 0000 || 0101 || 0010 || 0110 || 1111 || 0000 || 1010 || 0010 || 1100 |- | 24,8°C || 49% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 1001 || 0010 || 1111 |- | 24,9°C || 49% || 0000 || 0101 || 0100 || 1001 || 1111 || 0000 || 1001 || 0010 || 0111 |- | 24,7°C || 50% || 0000 || 0101 || 0100 || 1110 || 1111 || 0000 || 0000 || 1010 || 0001 |- | 24,8°C || 50% || 0000 || 0101 || 0100 || 0001 || 1111 || 0000 || 0000 || 1010 || 1110 |- | 24,6°C || 51% || 0000 || 0101 || 0100 || 0110 || 1111 || 0000 || 1000 || 1010 || 0001 |- | 15,7°C || 52% || 0000 || 0101 || 0100 || 1011 || 1001 || 0000 || 0100 || 1010 || 0110 |- | 15,9°C || 52% || 0000 || 0101 || 0100 || 1111 || 1001 || 0000 || 0100 || 1010 || 0010 |- | 16,1°C || 52% || 0000 || 0101 || 0100 || 1000 || 0101 || 0000 || 0100 || 1010 || 1000 |- | 16,3°C || 52% || 0000 || 0101 || 0100 || 1100 || 0101 || 0000 || 0100 || 1010 || 1111 |- | 14,9°C || 53% || 0000 || 0101 || 0100 || 1010 || 1001 || 0000 || 1100 || 1010 || 1011 |- | 15,1°C || 53% || 0000 || 0101 || 0100 || 1110 || 1001 || 0000 || 1100 || 1010 || 1101 |- | 15,5°C || 53% || 0000 || 0101 || 0100 || 1101 || 1001 || 0000 || 1100 || 1010 || 1110 |- | 11,7°C || 62% || 0000 || 0101 || 0100 || 1010 || 1110 || 0000 || 0100 || 0110 || 1111 |- | 11,8°C || 61% || 0000 || 0101 || 0100 || 0110 || 1110 || 0000 || 1000 || 0110 || 1111 |- | 11,9°C || 61% || 0000 || 0101 || 0100 || 1110 || 1110 || 0000 || 1000 || 0110 || 0111 |- | -0,1°C || 89% || 0000 || 0101 || 0000 || 1111 || 1111 || 1111 || 1001 || 0001 || 1110 |- | -0,2°C || 89% || 0000 || 0101 || 0000 || 0111 || 1111 || 1111 || 1001 || 0001 || 0001 |- | -2,5°C || 89% || 0000 || 0101 || 0000 || 1110 || 0111 || 1111 || 1001 || 0001 || 0000 |- |} =="Immer" gleich== "Sie kam aus einem kleineren Ort, wo das Motto galt: 'Wenn du nicht weiter weißt, schlachte ein Schwein'" (na, welcher Film war's?) Wie dem auch sei, zu erst einmal kann man die Bits ausschließen, bei denen nichts passiert. Bei meinen Messungen waren es Nibble 0 und 1. ==Luftfeuchtigkeit== Der Einfachheit halber kommt als erstes die Luftfeuchtigkeit dran. Dazu wurde die Excel-Tabelle nach dieser Spalte sortiert Da in einigen Datensätzen die Luftfeuchtigkeit konstant, die Temperatur jedoch unterschiedlich ist, kann man mit relativ wenig Aufwand die zuständigen Bits ermitteln. Dabei hilft es ungemein, die Bits in Gruppen zu unterteilen. Da sich 36 Bits gut durch 4 teilen lassen, habe ich diese Aufteilung gewählt. Excel-Formeln können beim Auseinanderpflücken der Datenworte enorm helfen (siehe Excel-Sheet). Die entsprechenden Spalten waren schnell gefunden: Nibble 6 und 7. Zum Dekodieren ist es am einfachsten, ähnliche Werte miteinander zu vergleichen. So sieht man z. B. bei den Werten 50% und 51% dass sich bei 51% das höchstwertigste Bit in Nibble 6 ändert. Bei 52% ist nur das zweithöchste Bit aktiv. Ein Muster?! Hilfreich ist hier die Exce-Funktion BININDEZ(), die Binär- in Dezimalwerte umrechnet. Da sich hier aber die höherwertigen Bits "früher" ändern als die niederwertigen ist anzunehmen, dass das Bitmuster verdreht ist. Eine Funktion zum Umkehren von Strings gibt es in Excel anscheinend nicht, allerdings kann man in den Formeln selbstdefinierte Funktionen verwenden. Diese ist in VBA schnell geschrieben: <source lang="VB"> Public Function Reverse(str as String) As String Reverse = StrReverse(str) End Function </source> BININDEZ(Reverse(<Zelle>)) angewendet auf Nibble 6 gibt die Einerstellen aus, Nibble 7 entspricht den Zehnerstellen. Volltreffer! ==Temperatur== Geht man wie bei der Luftfeuchtigkeit vor und sucht Werte mit der kleinstmöglichen Änderung, landet man sehr schnell bei 11,7, 11,8 und 11,9°C. Da Nibble 0, 1, 6 sowie 7 wegfallen, bleiben nur noch Nibble 3. Nibble 8 ist zwar bei 11,8 und 11,9°C unterschiedlich, bei 11,7 und 11,8°C gleich. Wendet man wieder die Excel-Formel von oben an, kommt man in vielen Fällen auf die richtige Nachkommastelle. Für eine vollständige Temperatur ist das natürlich noch nicht genug. Wandelt man Nibble 4 auf die gleiche Weise um, und addiert es um 4 Bit verschoben (bzw. mit 16 multipliziert) mit Nibble 3, hat man einen Temperaturbereich von 25,5°C eingeschlossen. Mit Nibble 5 Wächst der Informationsgehalt auf 12 Bit, also auf 2<sup>12</sup>=4096, was 409,5°C (unter Beachtung von 0°C) entsprechen würde. Das ist natürlich Blödsinn - eher schmilzt der Sensor ;-) Der Grund hierfür ist bei den negativen Temperaturen zu finden (die die Anzahl der Bits nochmals bestätigen), die im [[wpde:Zweierkomplement|Zweierkomplement]] übertragen werden. Dadurch verliert man ein Bit an das Vorzeichen, was immerhin noch Temperaturen von -104,8 bis 204,7°C ermöglichen würde. Der Grund für diesen weiten Anzeigebereich dürfte sein, dass das Rechnen mit 4 Bit einfacher ist, als etwas krummes zu verwenden (aber nur eine Annahme). ==Schalter== Der Sender hat, wie oben im Bild gezeigt, einen Kanalwahlschalter. Dieser Kanal müsste also auch bei der Übertragung mitgesendet werden. Hier ist die Ermittlung denkbar einfach: Umschalten und warten, bis Pakete eintreffen. Diese Information ist in den niederwertigsten zwei Bits (bei Beachtung des "Bitreversals") von Nibble 2. Etwas verwirrend ist hierbei, dass die Bits widerum vertauscht sind. ==Synchronisierung== Beim Herumspielen ist mir aufgefallen, dass das manuelle Synchronisieren von Sender und Empfänger zu einem Piepsen der Wetterstation führt. Also muss dies auch übertragen werden. Gleiches wie bei der Schalterstellung: Daten einfangen und vergleichen. Die Information steckt im 3. Bit von Nibble 2 (ebenfalls nach Bitreversal). ==Low Battery== Wenn man schräg auf das Display der Wetterstation schaut, sieht man ein Low-Battery-Symbol neben der Anzeige der Außentemperatur. Auch diesen Zustand kann man sehr einfach erreichen, indem man die Batterien durch ein Labornetzteil ersetzt. Nach Herunterdrehen des Potis erschien tatsächlich das Symbol im Display. Der Logic Analyzer sagt: Nibble 3, niederwertigstes Bit (muss ich Bitreversal noch erwähnen?). ==Rest== Damit wären eigentlich alle nötigen Informationen entschlüsselt. Es bleiben "nur noch" 12 Bit übrig. Wegen der Anordnung vermute ich hinter dem letzten Nibble eine Prüfsumme. Da sich das erste Nibble nur nach Batteriewechsel änderte, gehe ich davon aus, dass es sich um eine Zufällige Bitfolge zur Erweiterung des Addressraum handelt. Die restlichen 4 Bit sind mir bis dato noch gänzlich unbekannt. ==Prüfsumme== Ich mag sie (zumindest bei Reverse Engineering) einfach nicht. Hauptgrund ist, dass es schlichtweg beliebig viele Verfahren gibt, diese zu berechnen. Egal ob CRC, XOR oder eine einfache Summe wie beim [[ECL-Bus-Decoder]] - es ist einfach undankbar, diese zu rekonstruieren. Aber genug gejammert, Sicherheit kostet nunmal Aufwand. Am Anfang habe ich noch per Bruteforce versucht, die Prüfsumme zu ermitteln, indem ich einfach alle Werte ver-CRC-t, mit XOR verprügelt und addiert habe. Das führte nicht unbedingt zum erwünschten Erfolg - wobei ich dazu sagen muss, dass ich dort auch noch mit der Datenfolge in Reinform (also ohne das umdrehen der 4-Bit-Gruppen) gearbeitet habe. Im zweiten Versuch ging ich wieder über Excel (diese Programm wird man einfach nicht los) - dieses mal mit umgedrehten 4er-Gruppen. Dieses Mal war auch der Ansatz etwas anders: ich suchte mir die Datenpakete mit dem geringsten [[wpde:Hammingabstand|Hammingabstand]] - also jene Datenpakete, die möglichst wenige unterschiedliche Bits haben - heraus, was mehr Erfolg versprach. In der Excel-Datei (Name) habe ich meine "Forschungsergebnisse" zusammengefasst. Es handelt sich tatsächlich nur um eine Quersumme der Nibbles 0 bis 7, die im Modulo 16 mit Nibble 8 ver-XOR-t werden. Kommt 15 heraus, ist alles ok, bei jedem anderen Wert hat das Paket was abbekommen. Mit vorletztem Satz ist der Pseudo-Code <pre> summe := Summe(nibble[0 .. 7]) Binär_AND 0x0F WENN (summe Binär_XOR nibble[8]) = 0x0F DANN "Paket ok" ANDERNFALLS "Paket nicht ok" ENDE WENN </pre> gemeint, falls das besser verständlich ist. ==Zusammenfassung== {| class="wikitable" | '''Nibbles''' | colspan="4" align="center" | Nibble 0 | colspan="4" align="center" | Nibble 1 | colspan="4" align="center" | Nibble 2 | colspan="4" align="center" | Nibble 3 | colspan="4" align="center" | Nibble 4 | colspan="4" align="center" | Nibble 5 | colspan="4" align="center" | Nibble 6 | colspan="4" align="center" | Nibble 7 | colspan="4" align="center" | Nibble 8 |- | '''Empfangen''' | 0 || 0 || 0 || 0 || 0 || 1 || 0 || 1 || 0 || 1 || 0 || 0 || 1 || 1 || 0 || 0 || 1 || 1 || 1 || 1 || 0 || 0 || 0 || 0 || 0 || 0 || 1 || 0 || 1 || 0 || 1 || 0 || 0 || 0 || 0 || 1 |- | '''Bit-Reversal''' | 0 || 0 || 0 || 0 || 1 || 0 || 1 || 0 || 0 || 0 || 1 || 0 || 0 || 0 || 1 || 1 || 1 || 1 || 1 || 1 || 0 || 0 || 0 || 0 || 0 || 1 || 0 || 0 || 0 || 1 || 0 || 1 || 1 || 0 || 0 || 0 |- | '''Bezeichnung''' | colspan="4" align="center" | Adresse | ? | Sync | colspan="2" align="center" | Schalter | ? | ? | ? | Low Bat | colspan="4" align="center" | Temp 0 | colspan="4" align="center" | Temp 1 | colspan="4" align="center" | Temp 2 | colspan="4" align="center" | Hygro 0 | colspan="4" align="center" | Hygro 1 | colspan="4" align="center" | Prüfsumme |- | '''Bedeutung''' | colspan="4" align="center" | 0 | ? | nein | colspan="2" align="center" | 1 | ? | ? | ? | nein | colspan="4" align="center" | 3 | colspan="4" align="center" | 15 | colspan="4" align="center" | 0 | colspan="4" align="center" | 4 | colspan="4" align="center" | 5 | colspan="4" align="center" | 8 |} Die Temperatur lässt sich mit (3 + 15 * 16 + 0 * 256)/10 = 24,3 berechnen. Die Luftfeuchte entspricht 54% Die Prüfsumme hier ist 8, also müssen die restlichen Bytes 7 entsprechen: (0 + 10 + 2 + 3 + 15 + 0 + 4 + 5) AND 15 = 39 AND 15 = 7 7 XOR 8 = 15 => korrekt. =Software= Um weder Logic-Analyzer noch PC für die Erfassung der Außentemperatur und Luftfeuchte zu bemühen, soll der Code wieder auf einen Mikrocontroller. Aus gewohnheit kommt wieder ein AVR ATmega8 zum Einsatz. Zur bequemen Auswertung habe ich dieses mal den ICP (Input Compare Pin) bemüht. Da ich bis jetzt keine größere Erfahrung mit dem Komparator hatte, inspirierte ich mich ein wenig an der Atmel AppNote [http://www.atmel.com/Images/doc8014.pdf AVR135]. Diese beschreibt die Auswertung des Duty-Cylces eines PWM-Signals, also genau das, was man für den Empfänger braucht.= Um einen ungefähren Ausgangswert zu haben, eine kleine Rechnung: das kürzeste Signal hat eine Pulsweite von etwa 2ms, das längste 9ms. Diese müssen also zuverlässig erkannt werden. Der AVR läuft mit 12MHz (der Quarz steckt noch vom [[EMR7370]] im Breadboard), wodurch der AVR eine Zyklusdauer von 83,33ns entspricht. 8ms enstprechen genau 96000 Taktzyklen - etwas viel für den 16-Bit-Timer. Mit dem großzügigen Vorteiler 1024 kommt man auf knapp 94. Bleib noch die Frage, ob die 2 und 4ms sauber unterschieden werden können. 2ms entspricht 23 Timerzyklen, 4ms 47 - also durchaus brauchbare Werte. Zur Bestätigung dieser Theorie baute ich die AppNote so um, dass sie mir die Zählerstände für die jeweiligen High-Zyklen ausgab - mit durchschlagendem Erfolg. Zwar wackelten die Werte ein wenig, das aber im mehr als vertretbaren Rahmen. Zur Auswertung wird eine kleine Statemachine verwendet, was sich schlimmer anhört, als es eigentlich ist. In einer Variable wird der Zustand des Empfangs geschrieben: Warten auf Paket, Synchronisiert + Datenempfang, Fertig. Wird ein Paket empfangen, werden die Bits in ein Array geschrieben und ein Zähler hochgezählt. Ist dieser bei 36 (der Anzahl der Bits) angelangt, geht der Empfänger in den Zustand Fertig über und keine weiteren Bits werden eingelesen. Ist die Auswertung abgeschlossen, geht der Zustand in "Warten" zurück. Wird eine Pulslänge empfangen, die weder einer 1, 0 noch Sync entspricht, wird der Automat ebenfalls in Warten zurückgesetzt, wodurch die zuletzt empfangenen Bits verworfen werden. ==Der Trick mit den Bits== Zunächst habe ich Bits einfach wie sie gekommen sind in den Array geschrieben und erst zur Auswertung in die richtige Reihenfolge gebracht. Das kostet Zeit und Speicher, was sich durch geschickten Code minimieren lässt. Schaut man sich das Nibble-weise Bitreversal genauer an, {| class="wikitable" |- ! Bit mit Nr. !! (Binär) !! soll in Spalte !! (Binär) |- | 0 || 0000 || 4 || 0100 |- | 1 || 0001 || 5 || 0101 |- | 2 || 0010 || 6 || 0110 |- | 3 || 0011 || 7 || 0111 |- | 4 || 0100 || 0 || 0000 |- | 5 || 0101 || 1 || 0001 |- | 6 || 0110 || 2 || 0010 |- | 7 || 0111 || 3 || 0011 |} sieht man, dass man für die Zuordnung eigentlich nur Bit 3 kippen muss. Alle Bits ab Bit 4 kann man für die Zuordnung der Bytes verwenden, was im Quellcode wie folgt aussieht: <source lang="c"> if(bit == TCM_BIT_1) { uint8_t bytepos = tcm_pos >> 3; uint8_t bitpos = (tcm_pos ^ 4) & 7; tcm_bits[bytepos] |= 1<<bitpos; } </source> Das spart wenn ich mich recht erinnere knapp 40 Byte und wahrscheinlich einige Zyklen in der CPU. [[Kategorie:Reverse Engineering]] [[Kategorie:Wetterstation]] [[Kategorie:Zerlegt]] 9e5294bf357c0f37f1f768588e7726873305ac95 Reparatur iTP A3 EOS 0 385 1808 1743 2022-11-10T21:36:20Z Chris 2 wikitext text/x-wiki [[Datei:iTP_Gesamt.jpg|thumb|iTP A3 EOS im Vergleich zu einer AA-Zelle]] Vor ein paar Jahren habe ich mir eine iTP A3 EOS (upgraded) zugelegt. Wem die Bezeichnung nichts sagt: keine Sorge, muss man nicht kennen - es handelt sich dabei um eine Taschenlampe. Sie hat bis zu 96 Lumen (in 3 Stufen), obwohl sie nicht besonders größer als eine AA-Batterie ist (14 mm Durchmesser, 67 mm lang). Versorgt wird sie durch eine einzelne AAA-Zelle wobei der eingebaute Schaltwandler bis knapp 0,9 Volt läuft. Er holt also fast alles aus der Zelle, auch wenn die Taschenlampe zum Ende hin etwas dunkler wird. Das Teil ist - wie so vieles - toll, solange es funktioniert. Nachdem das Lämpchen immer am Schlüsselbund ist und dementsprechend öfter mal runter fiel, war nach knapp drei Jahren Schluss. Erst ging sie erst nach zudrehen und anschnippen an, später musste man etwas klopfen, dann blieb sie dauerhaft aus. Grmpf. Wegwerfen? Auf keinen Fall! Zumal es sie anscheinend nicht mehr zu Kaufen gibt. = Auf das Ding! = Das wahrscheinlich schwierigste Unterfangen an der Reparatur - Der Kopf der Lampe ist schnell drunten, aber wie kommt man an die Elektronik? Zwei Löcher in der Leiterkarte und das Gewinde verraten den Trick: Rausschrauben. Dazu nimmt man am besten eine ältere und sehr stabile Pinzette oder spannt zwei passende Stahlstifte (am besten mit Absatz oder konisch, damit man innen nichts aufspießt) in einen Schraubstock. <gallery> Datei:iTP_Kopf.jpg|Taschenlampenkopf von hinten Datei:iTP_oeffnen.jpg|Einrasten & Drehen </gallery> Erschwerend kommt dazu, dass der Innenkörper mit dem Lampenkopf verklebt wurde. Dagegen arbeitet man am besten mit Wärme und sanfter Gewalt. Es hilft auch, den Innenkörper immer wieder ein Stück hineinzudrehen. Hat man das Innenleben befreit, ist es empfehlenswert, die Klebereste vollständig zu entfernen - sowohl am Innenteil als auch am Lampenkopf. Sonst wird das Einschrauben später noch schwieriger. Dazu am Besten wieder erwärmen und vorsichtig (das Alu ist relativ weich) die Gewindegänge auskratzen. <gallery> Datei:iTP_Innenkoerper_oben.jpg|Helle Seite... Datei:iTP_Innenkoerper_unten.jpg|...und dunkle Seite des Innenkörpers </gallery> Um an die Elektronik zu kommen, muss zunächst die Leiterkarte runter, die zugleich den Kontakt zur Batterie darstellt. Dazu geht man am besten mit einem feinen Schraubendreher in die Nut und hebelt sie vorsichtig heraus. Wärme hilft auch hier gegen den Kleber. Oft sieht man nach diesem Schritt schon den Defekt: <gallery> Datei:iTP_Leitungsbruch1.jpg Datei:iTP_Leitungsbruch2.jpg Datei:iTP_Leitungsbruch3.jpg </gallery> Leitungsbruch. = Reparatur = Damit das Löten einfacher vonstatten geht (es ist verdammt eng!) habe ich bei meinen beiden Reparaturen auch die LED herausgenommen. Dazu muss man auf der anderen Seite des Innenteils zuerst die Plastikabdeckung herausnehmen und anschließend die Anschlussdrähte ablöten. <gallery> Datei:iTP_LED1.jpg|Mit Deckel Datei:iTP_LED2.jpg|Ohne Deckel Datei:ITP Waermeleitpaste.jpg|Ohne LED aber mit Pampe Datei:iTP_LED3.jpg|Ohne LED und Pampe </gallery> Da die Wärmeleitpaste eh eingetrocknet ist, kann man sie auch gleich entfernen/erneuern. Isopropanol und Wattestäbchen sind hier die Mittel der Wahl. Wenn man das Teil schon einmal offen hat: Am besten beide Leitungen zum Batteriekontakt tauschen! Ich habe bei der ersten Reparatur vor einem halben Jahr den Fehler gemacht, nur die gebrochene Leitung neu anzulöten und durfte das Teil jetzt noch einmal öffnen. Die beiden Litzen sind recht kurz zu halten, 1 cm ist mehr als genug. Auf jeden Fall sollte man eine feine Litze nehmen (meine ist schon fast zu dick), damit die Lötstellen nicht wieder so schnell brechen. = Zusammenbau = Und schon liegt das Teil wieder da wie eine aufgebrachte Krabbe - bis man es wieder in die Behausung steckt: <gallery> Datei:iTP_Zusammenbau1.jpg|[http://www.youtube.com/results?search_query=findet+nemo+krabben+hey Hey!] Datei:iTP_Zusammenbau2.jpg|Zusammengeklappt Datei:iTP_Zusammenbau3.jpg|und wieder eingebaut </gallery> Wichtig beim Zusammenbau: die Drähte für die LED durch die Löcher stecken und dann die Elektronik um 180 Grad drehen, sonst schauen die Drähte viel zu weit heraus. (Alternativ: zuerst LED anlöten und dann die Elektronik ins Alugehäuse einsetzen) Die vorher entfernte Wärmeleitpaste durch neue ersetzt (wie beim PC gilt: weniger ist manchmal mehr und bei mir ist es fast schon zu viel) und schon kann man die LED wieder anlöten. Beim Anlöten der Drähte an die LED müssen diese gegen den Uhrzeigersinn liegen (siehe oben), sonst passt die Plastikkappe nicht! Bei der LED sind übrigens sowohl Anode als auch Kathode auf der Trägerplatine markiert (+ und -) Die Kontaktplatine wieder eingedrückt (wenn sie fest hält, muss man sie nicht einmal verkleben) kann das Modul wieder ins Gehäuse. Und sie leuchtet wieder! [[Kategorie:Elektronik]] [[Kategorie:Reparatur]] [[Kategorie:Beleuchtung]] [[Kategorie:Zerlegt]] 0ec7e7614dcae4a0c2fbd65ebe57be2e17502267 Reparatur R&S CMU200 Hintergrundbeleuchtung 0 669 1809 1484 2022-11-10T21:36:28Z Chris 2 wikitext text/x-wiki In der Arbeit wurde ein Schwung [https://www.rohde-schwarz.com/de/produkt/cmu200-produkt-startseite_63493-7830.html Rohde und Schwarz CMU200] ausgemustert. Für die, die sie nicht kennen: Eine CMU ist ein "Universal Radio Communication Tester", ausgerichtet auf Mobilfunktelefone. Kurzum: eine kleine Handy-Basisstation mit vielen möglichen Optionen, von GSM über WCDMA und HSPA, ..., aber auch Bluetooth. Das bedeutet aber nicht, dass man mit dem Teil zum Mobilfunkbetreiber werden kann, im Gegenteil: es dürfte ziemlich dumm sein, anstatt eines geschirmten Koppler eine "offene" Antenne anzuschließen. Aber was macht man als Bastler mit dem Teil, außer etwas ältere Technik zu bewundern? Ganz einfach: zu den Basisfunktionen gehören ein relativ gutes Frequenznormal, ein Signalgenerator mit verschiedenen Modulationsarten und ein ordentlicher Spectrum Analyzer. Auf einem der Geräte war ein Aufkleber "Display defekt". Die meisten Displays aus der Zeit haben noch ein eine Hintergrundbeleuchtung mit CCFL-Röhren und viele verwechseln ein kaputtes Display mit einem kaputten Backlight - also ab in den Kofferraum mit dem Teil. Wenn man im zweiten Stock ohne Aufzug wohnt merkt man, wie solide Geräte aus dem Hause Rohde und Schwarz gebaut sind, "das gilt als Sport". Am Strom surren die Lüfter und die Festplatte vor sich hin und das Display bleibt erwartungsgemäß dunkel. Der einfachste Test für LCDs ist, mit der Taschenlampe hineinzuleuchten und siehe da: dunkel schimmert die Benutzeroberfläche. Praktischerweise hat das Teil auch einen VGA-Ausgang, der auch gut funktioniert. Damit wäre der Artikel im Prinzip auch schon zu Ende. Falsch gedacht, er fängt erst an: =Auf das Ding!= Ein kurzer Abstecher [https://duckduckgo.com/?q=CMU200+service+manual ins Internet] fördert Service Manuals zu Tage. Ab der Hälfte des Manuals mit "other" im Namen steht dann sogar, wie man das Gehäuse öffnet: Gehäuse auf die Front legen (sofern die Griffe vorhanden sind) und hinten die Füße mit einem T20 Torx abschrauben. Nun kann man die Hülle herunterziehen und legt den Zugriff zu allen weiteren Schrauben bei. <gallery> cmu200_schrauben1.jpg | Mit einem T20 Schraubendreher und Zielvermögen lassen sich die Füße entfernen </gallery> Hier sieht man auch, wo man das Geld für ein Einfamilienhaus stecken konnte: In Module (und Lizenzen). Um an das Display zu kommen, müssen zunächst die vorderen Griffe ab, die zugleich auch die Frontblende am Gehäuse fixieren. Im Anschluss können die hinteren Schrauben am Frontmodul ringsum und die am Halteblech des nach hinten ragenden Moduls sowie dem PCMCIA-Adapter gelöst werden: <gallery> cmu200_schrauben2.jpg | 5 Schrauben oben, cmu200_schrauben3.jpg | 4 unten cmu200_schrauben4.jpg | und jeweils 2 cmu200_schrauben5.jpg | an den Seiten </gallery> Mit einem vorsichtigen Ruck kann man nun das Frontmodul vom Rest befreien. Je nach Ausbaustufe muss man auch ein paar Flachbandkabel abziehen. Hat man das Frontmodul auf dem Schreibtisch, heißt es wieder: ringsum Schrauben lösen. Allerdings ist man dann noch nicht am Ende: noch einmal darf man rundherum den schraubendreher schwingen. Immerhin: alle Schrauben haben die gleice Größe. <gallery> cmu200_schrauben6.jpg | Leider nur von einer Seite, das Prinzip ist aber klar cmu200_schrauben7.jpg | Endlich am Enbedded-PC angekommen, cmu200_schrauben8.jpg | sofern man willens ist, noch cmu200_schrauben9.jpg | ein paar mehr Schrauben zu drehen </gallery> Jetzt man kann (vorsichtig!) das Display vom Embedded-PC trennen. Am besten zuerst die Verbindung der Folientastatur lösen, anschließend die Flachbandkabel für Display und Jogdial. Leider habe ich hiervon kein Foto gemacht. =Backlight-Tausch= Obwohl ich mich schon darauf eingestellt habe, das Display komplett zu zerlegen ist es durchaus wartungsfreundlich - die Röhre lässt sich als Modul mit zwei Schrauben entfernen: <gallery> cmu200_display1.jpg | Display mit Abdeckung der Röhre cmu200_display2.jpg | Display ohne Abdeckung der Röhre cmu200_display_inverter.jpg | Inverter der Hintergrundbeleuchtung </gallery> Das erste Foto ist leider gestellt - die CCFL habe ich bei erster Gelegenheit entfernt, da die Ausdünstungen bei einem Bruch nicht unbeding gesundheitsförderlich ist. Der Inverter ist auch bei erster Gelegenheit rausgefallen. Der Inverter ist ebenfalls ein eigenes Modul - ein 810-CXA-L0605-VJL von TDK. [https://www.mouser.de/ProductDetail/TDK/CXA-L0605-VJL?qs=lq5%252BOP7PS09Q7ZKD1DX6Kw%3D%3D Mouser] hat sogar noch ein Datenblatt, das ein paar meiner Hoffnungen zerstört. Leider wird das Teil mit 5 Volt und nicht mit LED-Streifen-freundlichen 12 V betrieben. Laut Datenblatt genehmigt sich das Teil bis zu 0,8 A, also 4 Watt. Damit sollte man das Displays mit LEDs sehr hell bekommen. Aber zunächst muss man sie überhaupt montieren können. Der Originalrahmen ist, als hätte es Sharp geahnt, knapp 8 mm tief, sehr passend zu marktüblichen LED-Streifen. Meine Wahl fällt auf das, was rumliegt: kaltweiße Streifen mit 60 PLCC2-LEDs pro Meter. Nicht die hellsten oder besten am Markt, aber sie sind da. Die nächste Frage stellt sich sogleich: wie montieren? Im Baumarkt werde ich fündig: ein [https://www.bauhaus.info/metallprofile-kunststoffprofile/kantoflex-winkelprofil/p/10522351?adb_search=25642 L-Profil mit 7,5 x 12,5 mm], 1 m für 1,45 Euro. Nicht ideal, aber die Welt ist eben voller Kompromisse. Auf 13,5 und 18 cm abgelängt, mit 45° gegehrt passen die Profile sehr gut ans Display - und auch die LED-Streifen passen wie angegossen. Mit etwas Kapton-Tape ist auch sichergestellt, dass es am Ende der Streifen keine Kurzschlüsse gibt. <gallery> cmu200_display3.jpg | gesägte und beklebte Aluprofile cmu200_display4.jpg | mit guter Passform cmu200_display5.jpg | auch wenn man genauer hinschaut </gallery> Bevor die Streifen fixiert werden muss natürlich getestet werden, mit welchem Abstand die Lichtausbeute und Konformität am besten ist. <gallery> cmu200_display6.jpg | Ausleuchtung mit LED-Hintergrundbeleuchtung </gallery> Stellt sich heraus: so nah wie möglich an den Lightspreader. Die auf den Fotos sichtbaren Leuchtpunkte fallen mit bloßem Auge kaum auf. Auch der Grünstich ist nicht ganz so heftig wie auf den Bildern zu sehen ist, aber dennoch vorhanden. Fixiert wird das Ganze nicht nur mit einer Portion Heißkleber, sondern auch mit Alutape - es soll ja nach was aussehen: <gallery> cmu200_display7.jpg | Angeheftet mit Heißkleber cmu200_display8.jpg | Flächenklebung mit Alutape </gallery> =LED-Treiber= Jetzt müssen nur noch die LEDs getrieben werden. Großartig in der Elektronik herumpopeln möchte ich nicht, wer weiß, wie die Stromversorgungen ausgelegt sind und wie empfindlich manche Rails sind. Da der CCFL-Treiber vermutlich auch nicht wenig herumgesaut hat, fiel die Wahl auf einen kleinen DC-DC-Wandler, der auf einem MT3608 basiert. Das Teil hat nur eine Marotte: Wenn man am Poti dreht, passiert erst sehr wenig, dann plötzlich sehr viel. Schaut man die Spindel nur mal kurz schief an, springt die Spannung von 12 V auf 14 V. Das möchte ich den LEDs nicht zumuten - und ja, LEDs treibt man eigentlich über den Strom. Der Spannungsteiler besteht aus einem 100 kOhm-Poti das gegen Masse über einen 2,2 kOhm-Widerstand "verlängert" ist. Die Ausgangsspannung berechnet sich nach: :<math>U_{\textrm{out}}=U_{\textrm{ref}} \cdot \left(\frac{x\cdot R_{\textrm{pot}}}{(1-x)\cdot R_{\textrm{pot}} + R_{\textrm{bot}}} + 1\right)</math> Mit <math>U_{\textrm{ref}}=0.6\ \textrm{V}</math> erhält man bei einem auf Anschlag gedrehtem Poti (<math>x = 1</math>) einen Wert von 27,87 V. Das ist ein bisschen zu viel. Schaut man sich an, wie sich die Ausgangsspannung über x (also der Potistellung) verhält, merkt man, dass das gar nicht mal so clever gemacht ist: <gallery> cmu200_vreg1.png | Ausgangsspannung in Abhängigkeit der Potistellung - Originalzustand </gallery> Stellt man die oben gezeigte Formel um, kann man mit <math>x = 1</math> und <math>U_{\textrm{out}}</math> als Maximalspannung den nötigen Bottom-Widerstand ermitteln: :<math>R_{\textrm{bot}} = R_{\textrm{pot}} \cdot \left( \frac{U_{\textrm{out}} \cdot x}{U_{\textrm{out}} - U_{\textrm{ref}}} - 1 \right)</math> Für <math>U_{\textrm{out}} = 13\ \textrm{V}</math> erhält man einen Widerstand von 4,8 kOhm, der nächste verfügbare ist 4,7 kOhm. Rechnet man nochmal "rück", kommt man auf eine maximale Ausgangsspannung von etwa 13,37 V. Passt soweit. Erwartungsgemäß verhält sich der Ausgang ähnlich exponentiell wie zuvor: <gallery> cmu200_vreg2.png | Ausgangsspannung in Abhängigkeit der Potistellung - mit 4,7 kOhm-Poti </gallery> Das Problem liegt im Nenner der Funktion: geht x gegen 1, wandert der Nenner gegen klein und die Gesamtfunktion "explodiert". Die Misere lässt sich mit einem Stück Draht beheben: Schließt man den "unteren Teil" des Potis kurz, wird <math>(1-x)\cdot R_{\textrm{pot}}=0</math> und der Term wird linear: <gallery> cmu200_vreg3.png | Ausgangsspannung in Abhängigkeit der Potistellung - mit 4,7 kOhm-Poti und einseitig gebrücktem Poti </gallery> Anhand des Datenblattes des ursprünglichen Treibers der Hintergrundbeleuchtung lässt sich die Pinbelegung ermitteln: Blau ist Schwarz und Schwarz ist rot. Nein: Pin 1 ist Vin und Pin 2 GND. Pin 3 ist ein Remote Enable und an der 4 könnte man die Helligkeit einstellen. "Unwichtig" sagt der Bastler und irgendwo muss der Stecker ja befestigt sein. Damit sich das Poti nicht doch noch umentscheidet, wird die Einstellung mit Heißkleber fixiert. Die Montage im Gehäuse erfolgt über einen etwas länger gelassenen Schrumpfschlauch und der bereits vorhandenen Schraube. Damit nichts herumflattert (und in der Hoffnung, dass es in Sachen EMV hilft) kommt noch eine Lage Alutape drüber: <gallery> cmu200_display9.jpg | Anschluss an den Leitungssatz cmu200_display10.jpg | eingeschrumpft und angeschraubt cmu200_display11.jpg | und verklebt </gallery> =Wenn man schon dabei ist & Zusammenbau= Obwohl die CMU eher einfach zu Zerlegen ist, dauert es doch eine Weile, bis die Einzelteile auf dem Tisch liegen. Deshalb macht man am besten das, was man an der Stelle gut machen kann: Wartung. Das Lager der Lüfter hört man mittlerweile recht gut, passenden Ersatz habe ich aber nicht da, also bleibt der erst einmal so. Was aber immer geht und nach knapp 20 Jahren doch mal platt sein kann: die BIOS-Batterie. Alte raus, neue rein und wieder einige Jahre Ruhe. <gallery> cmu200_embedded_pc.jpg | Ein Blick auf das Mainboard </gallery> Es empfiehlt sich auch, ein Backup der Festplatte (z. B. mit [https://clonezilla.org/ Clonezilla]) anzulegen. Da es mittlerweile schwierig ist, 2,5"-Festplatten mit P-ATA Interface zu bekommen: CF-Karten mit IDE-Adapter funktionierten zumindest bei einem anderen R&S-Gerät ausgezeichnet, inklusive kürzerer Boot-Zeiten. Wie langlebig ein solcher Aufbau ist - keine Ahnung. Das Zusammenbauen erfolgt genau rückwärts zum Zerlegen, wobei es ein paar Fallstricke gibt: Da die Stiftleiste für die Festplatte keine Wanne hat, muss man darauf achten, dass der Stecker richtig sitzt. Was auf dem ersten Blick ok aussieht, kann in Tränen enden: <gallery> cmu200_hdd1.jpg | sieht richtig aus cmu200_hdd2.jpg | ist aber falsch </gallery> Beim Aufstecken des Frontmoduls "darf" man unter Umständen ein paar Flachbandkabel einstecken, die allerdings passend beschriftet sind: <gallery> cmu200_flachbandkabel.jpg | W222 auf X222 </gallery> Etwas fummelig ist das auf jeden Fall vorhandene für die LEDs am Frontpanel - hier gibt es leider kein Patentrezept. Ich habe mit der einen Hand das Panel gehalten und mit der anderen das Kabel von unten in die richtige Position manövriert. Nun kommt auch die Stunde der Wahrheit: Noch bevor man den Deckel schließt, sollte man prüfen, ob die Kiste hochkommt. <gallery> cmu200_boot.jpg | Erfolg! </gallery> Im Anschluss packt man die übrig gebliebenen Schrauben in eine kleine Tüte und klebt sie mit Klebeband so auf die Abdeckung, dass sie nach unten herunterbaumeln. <gallery> cmu_restteile.jpg </gallery> Oder man sucht, wo sie tatsächlich hingehören, z. B. ans Bracket des PCMCIA-Slots und dem Niederhalter für die Einsteckkarte. [[Kategorie:Messequipment]] [[Kategorie:Reparatur]] [[Kategorie:Elektronik]] [[Kategorie:Zerlegt]] d1315517a7dab8d742920368c64c1bf38ad7c22d MediaWiki:Sidebar 8 8 1810 787 2022-11-10T21:39:44Z Qsysopr 1 wikitext text/x-wiki * navigation ** mainpage|mainpage ** http://hobbyelektronik.org/b/|Blog ** recentchanges-url|recentchanges ** randompage-url|randompage ** Spezial:Alle_Seiten|Alle Seiten * Bereiche ** Category:Elektronik|Elektronik (ohne µC) ** Category:AVR|AVR ** Category:PC|am PC ** Category:Software|Software (PC) ** Category:LCD|LCDs ** Category:Sonstiges|Sonstiges ** Category:Murks|Murks ** Category:Reparatur|Reparatur ** Category:Zerlegt|Zerlegt a3973bbf41f17be95ec70afcfb37957039a1b449 Umbau Belkin Auto-USB-Lader 0 345 1811 851 2022-11-10T21:40:40Z Qsysopr 1 wikitext text/x-wiki Meine Schwester braucht Strom fürs Handy im Auto und da es beim Mobilfunkanbieter mit dem roten Tropfen einen entsprechenden Adapter für 5 Euro gab, hat sie auch gleich zugeschlagen. Das Teil nennt sich "Belkin Micro USB Car Charger inkl. 30-Pin Sync-/Ladekabel" und hat die Produkt-Nummer F8J056. Einen kleinen Nachteil hat das Ding allerdings: "Designed for products with half-eaten fruits". Natürlich funktioniert es auch mit anderen Geräten, dann aber nur innerhalb (trotzdem nicht ganz eingehaltenen) USB-Spezifikation - also 500 mA. Besonders wenn man rechenlastige Dinge wie Navigation macht, kann da die Luft dünn werden. =Die Theorie= Um gut mit Android-Geräten zu funktionieren muss der Adapter umgebaut werden. Bei dem Apple-Zeug müssen die USB-Datenleitungen D+ und D- über Spannungsteiler auf ca. VBus/2=2,5 V gebracht werden, wobei meines Wissens auch der Strom (und damit die Widerstandswerte) definiert sind. Bei Androiden müssen üblicherweise D+ und D- miteinander verbunden werden. Das könnte man auch mit einem Zwischenstecker oder umgebauten USB-Kabel machen, aber das ist langweilig und kann jeder. =Auf die Dose!= [[Datei:Belkin_F8J056_offen.jpg|thumb|Geöffneter Ladeadapter]] Hier beginnt auch schon das Problem: Das Gehäuse ist ziemlich gut verschlossen. Zwischen den Massefedern außen sieht man allerdings eine feine Naht, die einen Angriffspunkt darstellt. Mit einem großen flachen Schraubendreher lassen sich die Gehäusehälften bei den Federn auch etwas auseinander biegen, mit sehr viel sanfter Gewalt kann man sich mit einem zweiten (feinen) Schraubendreher an der kompletten Kante entlang arbeiten. Am besten, man klemmt den Adapter in einen Schraubstock ein. Ich habe dabei ([http://hobbyelektronik.org/b/2011/08/stigmata/ mal wieder]) die Erfahrung gemacht, dass sich die Spitze von Schraubendrehern und Handinnenflächen nicht unbedingt vertragen (nach knapp 14 Tagen ist es immerhin wieder fast verheilt). Auf jeden Fall war das Teil damit auch geöffnet Die Leiterplatte bekommt man am besten heraus, indem man ein USB-Kabel einsteckt, und vorsichtig (!) hebelt. Zum Vorschein kommt folgendes Platinchen: <gallery> Datei:Belkin_F8J056_pcb_top.jpg|Leiterplatte von oben Datei:Belkin_F8J056_pcb_bot.jpg|Leiterplatte von unten </gallery> Sieht auf den ersten Blick gar nicht mal so übel aus. Nicht dieses Standard-biestige-MC34063-Design, sogar eine Polyfuse und Verpolungsschutz am Eingang wurden spendiert. Der Schaltwandler selbst (etwas anderes kann man sich aufgrund der relativ großen Induktivität, der dicken Diode und vor allem der ordentlichen 2 A am Ausgang nicht vorstellen) sitzt unter dem großen Masseblech und ermöglicht zusätzliche Wärmeabführung. Also auch mechanisch ganz nett designed. Wie dem auch sei, nachdem auf der Oberseite keine Widerstände zu sehen sind, müssen sich diese unterm Blech befinden, also weg damit: <gallery> Datei:Belkin_F8J056_pcb_bot2.jpg|Leiterplatte von unten, ohne Blech </gallery> =Umbau= Zum Vorschein kommt ein NT3875A von Noveltek, der laut Datenblatt genau für diesen Zweck gemacht ist. Unter der USB-Buchse befinden sich auch ein paar Widerstände, die mit den Datenleitungen verbunden sind. In der Schaltung gemessen ergibt sich: <math>R7 = \infty; R8 = 33,4 \textrm{ k}\Omega; R9 = 24,25 \textrm{ k}\Omega; R11 = 24,5 \textrm{ k}\Omega; R10 = 31,35 \textrm{ k}\Omega</math> Das Auslöten zeigt: Wer misst, misst mist und natürlich: Niemals im eingebauten Zustand messen! Denn tatsächlich verhalten sich die Widerstände wie folgt: <math>R7 = \infty; R8 = 75,2 \textrm{ k}\Omega; R9 = 43,1 \textrm{ k}\Omega; R11 = 50 \textrm{ k}\Omega; R10 = 50 \textrm{ k}\Omega</math> Im Endeffekt egal, denn sie kommen eh weg. Um D+ und D- zu verbinden, kann entweder R7 oder die oberen Pads von R8 und R9 gebrückt werden. Da die unter dem USB-Port liegende LED deutlich blendet, wurde deren Vorwiderstand (R6) gleich durch einen etwas größeren (4,7 k) ersetzt. Weil ich nix in 0402 bzw. 0603 da hatte, musste dann halt ein querliegender Widerstand in der Baugröße 0805 herhalten: <gallery> Datei:Belkin_F8J056_umgebaut.jpg|Neuer Widerstand für die LED </gallery> Ans Handy geklemmt zieht das Teil bei 12 V Eingangsspannung 0,42 A, also gehen 5W (bei meinem etwas älteren HTC) in den Akku. Passt. =Zusammenbau= Der Zusammenbau ist relativ einfach - Metallbügel anlöten, im Gehäuse versenken und dieses verschließen. Hier reicht stecken alleine nicht, es will geklebt werden. Mit 2-Komponenten-Kleber eine sichere Sache: Einmal an der Rundung entlang, etwas an den Gehäusekanten dran (nicht zu viel!) und an der "Spitze" sehr vorsichtig agieren! Läuft die Brühe bis zum [http://hamburgforbeginners.wordpress.com/2008/10/13/pinopel/ Pinöpel] vorne, kann es zu Kontaktproblemen kommen. Mir ist es natürlich passiert - durch Drehen und vorsichtiges Drücken kann man ihn wieder frei bekommen. Besser ist es aber, es gar nicht so weit kommen zu lassen. [[Kategorie:Sonstiges]] [[Kategorie:Elektronik]] [[Kategorie:Zerlegt]] dabed1abd3f9dd4d5461497320fd1b9214698769 Datei:Prozeda rf200 prim vorlauf 56.jpg 6 810 1812 2022-11-11T21:53:14Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Prozeda rf200 prim vorlauf 57.jpg 6 809 1813 2022-11-11T21:53:14Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbus rxo brd.png 6 430 1821 1030 2022-11-22T20:34:13Z Chris 2 Chris lud eine neue Version von [[Datei:Vbus rxo brd.png]] hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbus rxo.zip 6 431 1822 1031 2022-11-22T20:35:07Z Chris 2 Chris lud eine neue Version von [[Datei:Vbus rxo.zip]] hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbus rxo sch.png 6 811 1823 2022-11-22T20:35:29Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder/Adapter für RS-232 0 704 1824 1600 2022-11-22T20:47:37Z Chris 2 Update: Fehler im Schaltplan wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann mit dieser Hardware den VBus anbinden. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. Vor geraumer Zeit habe ich ein kleines Design zum Mitlesen auf dem VBus am PC gemacht. In leicht abweichender Form wurde es auch aufgebaut und hat funktioniert. Das Leiterkärtchen ist etwa 27,5 x 23,2 mm groß und lässt sich direkt an einen D-Sub-Stecker anflanschen. Der MAX3232 erzeugt RS232-kompatible Pegel und die Versorgung wird vom VBus übernommen. <gallery> Vbus_rxo_sch.png|Schaltplan der PC-Hardware Vbus_rxo_brd.png|Layout der PC-Hardware </gallery> =Update 11/2022= Irgendwann wird jede Hardware mal nachgebaut. Hier hat es etwas länger gedauert und es wurde ein Fehler entdeckt, den ich selber nicht mehr so richtig nachvollziehen konnte: Die Schaltung funktionierte nicht mit einem LM393. Dieser hat Open-Drain-Ausgänge, die Schaltung aber keine Pull-ups. Die Originalschaltung von Resol hat einen Komparator mit Push-Pull-Ausgängen verwendet, wo die Schaltung natürlich funktioniert. Aber nichts, was man nicht mit zwei Widerständen lösen könnte. Heute würde ich die Schaltung so nicht mehr auf- oder nachbauen - dafür funktioniert die Variante ohne zusätzliche Logikgatter zu gut. Ob es hier eine aktualisierte Version geben wird? Vermutlich nicht. Dafür ist RS-232 im Heimbereich mittlerweile schon fast zu selten. =Downloads= * [[Datei:Vbus_rxo.zip]] Design-Daten für die PC-Hardware. Erstellt mit EAGLE 7.7.0 [[Kategorie:PC]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 9d0296a22471a9b59a221e52f75deb392db38ae3 Datei:Resol sch.png 6 119 1825 388 2022-11-22T20:53:42Z Chris 2 Chris lud eine neue Version von [[Datei:Resol sch.png]] hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp carsten rx issue 2.png 6 812 1826 2022-11-24T20:17:43Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbusesp carsten rx issue 1.png 6 813 1827 2022-11-24T20:17:43Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder/Adapter für den ESP8266 0 757 1828 1763 2022-11-24T20:18:17Z Chris 2 Abschnitt "Bekannte Probleme" hinzugefügt wikitext text/x-wiki [[Bild:vbusesp_top.jpg|thumb|Aufgebauter Leiterkarte (v0.1)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Wenn Basteln und IoT aufeinandertreffen, kommt man fast nicht an den Mikrocontrollern von Espressif vorbei. Genau aus diesem Grund hatte ich schon länger die Idee, ein Leiterkärtchen mit dem ESP8266 zu machen. Also warum nicht einfach den beliebten VBus ohne großes Strippenziehen ins Netzwerk bringen? =Schaltung= Die Schaltung für den VBus basiert auf der für den [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Raspi (v1.3)]], aufseiten des ESP habe ich mich von den verschiedenen Bastelboards inspirieren lassen und die Möglichkeit vorgesehen, sowohl die kleinen ESP01- als auch die etwas vielseitigeren ESP12-Module einzusetzen. Die Versorgung findet über eine Stiftleiste (bzw. angelötete Drähte) oder über eine Micro-USB-Buchse statt. Diese dient nur der Stromversorgung - mehr zum Programmieren des ESP weiter unten. Bei der Verwendung des ESP12-Moduls stehen zusätzlich zum VBus-Interface noch die GPIOs 12, 13, 14 und 16 sowie der ADC-Eingang und die 3,3V-Versorgung zur Verfügung. Hier kann weitere Peripherie wie Sensoren oder Displays angeschlossen werden. Für den Aufbau gibt es mehrere Varianten, die unten aufgeführt sind. Diese können über die Tabs ausgewählt und müssen beim Besorgen der Bauteile und selbstverständlich beim Zusammenbau kombiniert werden. Die theoretische Maximalbestückung sieht wie folgt aus: <gallery> vbusesp_max_sch_1.png | Schaltplan VBus + Stromversorgung vbusesp_max_sch_2.png | Schaltplan ESP8266 und IO vbusesp_max_assy.png | Bestückungsplan </gallery> =BOM= Möglichkeiten schaffen Komplexität. Wie bei den anderen Plattformen lässt sich der Adapter in verschiedenen Varianten aufbauen, wobei ich (auch wenn es gerade bei dieser anbietet) noch immer empfehle, die Optoisolierte aufzubauen. ==Decoder== Neben Optoisoliert und Direkt gibt es noch die Variante ohne ESP - dank der Stiftleiste rechts oben auf der Leiterkarte lässt sich der VBus-Anteil komplett unabhängig vom ESP-Anteil verwenden. Mit Säge und Fingerspitzengefühl lässt sich die Größe auch noch ein gutes Stück reduzieren. Als ESP8266-Modul kann das ESP01 und ESP12(-F) verwendet werden. Getestet wurde bis jetzt nur das ESP12-F, wobei nichts gegen das 01 sprechen dürfte. <tabs> <tab name="Optoisoliert"> Empfohlene Bestückungsvariante. <gallery> vbusesp_optiso_sch_1.png | Variantenschaltplan VBus vbusesp_optiso_sch_2.png | Variantenschaltplan ESP8266 vbusesp_optiso_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 5 || R9, R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Direkt"> <gallery> vbusesp_direct_sch_1.png | Variantenschaltplan VBus vbusesp_direct_sch_2.png | Variantenschaltplan ESP8266 vbusesp_direct_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 4 || R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 2 || Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Optoisoliert (ohne ESP)"> Wer keinen ESP8266 verwenden aber die Vorzüge der verbesserten Schaltung haben möchte, kann den ESP-Anteil vollständig weglassen. Hierfür wird auf dieser Leiterkarte keine Stromversorgung benötigt, da diese vom jeweilig verwendeten Interface (z. B. SBC, USB-UART-Wandler, ...) bezogen werden kann. <gallery> vbusesp_optisonoesp_sch_1.png | Variantenschaltplan VBus vbusesp_optisonoesp_sch_2.png | Variantenschaltplan Interface vbusesp_optisonoesp_assy.png | Bestückungsplan vbusesp_vbusonly_pinout.png | Anschlussbelegung des UART </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> ==Stromversorgung== Für die Stromversorgung gibt es ebenfalls zwei Möglichkeiten: Entweder mit LDO oder Schaltwandler. Wer auf Nummer sicher gehen will, nimmt die billigere LDO-Variante, da ich noch keine Gelegenheit hatte letztere zu testen. Die etwas höhere Stromaufnahme dürfte wahrscheinlich nicht allzu sehr ins Gewicht fallen. <tabs> <tab name="Linearregler"> Empfohlene Bestückungsvariante. <gallery> vbusesp_vregldo_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregldo_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || REG1117 || SOT223 || NCP 1117 ST33T3G |} </tab> <tab name="Schaltwandler"> <gallery> vbusesp_vregsmps_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregsmps_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C9 || 100n || C0603 || X7R-G0603 100N |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C12 || 10p || C0603 || NPO-G0603 10P |- | 1 || R17 || 15k || R0603 || RND 0603 1 15K |- | 1 || L1 || 15u || 242408FPS || L-242408FPS 15µ |- | 1 || R16 || 47k || R0603 || RND 0603 1 47K |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || D6 || BAT43WS || SOD323-W || BAT 43WS |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || IC2 || MCP16301 || SOT23-6 || MCP 16301T-I/CHY |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || D4 || SS13L || SUBSMA || SS 13L |} </tab> </tabs> =Inbetriebnahme/Benutzung= ==Flashing== Wird ein ESP8266 verwendet, muss natürlich erst einmal die Software auf den Mikrocontroller. Das Problem: Der Softwaredownload findet über den selben UART statt, der auch für das VBus-Interface statt. Nun könnte man mit Multiplexern arbeiten, was im Idealfall nur einmal benutzt werden würde und somit mit Kanonen auf Spatzen geschossen wäre. Aus dem gleichen Grund gibt es keinen USB-UART-Konverter auf dem Board: Braucht nur Platz und kostet. Deshalb wird für das erstmalige Flashen ein USB-UART-Adapter, der RTS/DTR anbietet, benötigt. Dieser sollte idealerweise mit 3,3 V arbeite, wobei der ESP wohl auch 5 V toleriert. Die beiden Transistoren für Reset und Bootloader nach WittyCloud/NodeMCU sind bereits vorhanden. Die 5 V-Stromversorgung muss entweder über den USB-Port oder der Stiftleiste SV2 kommen, die Anschlussbelegung des UART an SV4 ist wie folgt: {| class="wikitable" ! Pin || Signal vom UART-Adapter |- | 1 || DTR |- | 3 || TX |- | 7 || RX |- | 9 || RTS |} <gallery> vbusesp_prog_1.png | Anschlussbelegung für das Programmieren per UART vbusesp_prog_2.jpg | Verwendung des WittyCloud-USB-Wandlers </gallery> Liegt das Trägerboard eines WittyCloud herum, müssen DTR und RTS gefädelt werden. ==Betrieb== Ist die Firmware auf dem Chip und es sollen Daten vom VBus decodiert werden, muss ein Jumper zwischen Pin 3 und 4 an SV4 oder ein Lötpunkt auf SJ1 gesetzt werden: <gallery> vbusesp_txjumper.png | UART-Verbindung zwischen VBus und ESP8266 </gallery> =Firmware= Zugegebenermaßen: ich habe zwar seit Jahren ein paar ESP8266-Module herumliegen, mich aber nie so richtig damit auseinandergesetzt. Aber das macht nichts: [https://tasmota.github.io/docs/ Tasmota] unterstützt verschiedene [https://tasmota.github.io/docs/Smart-Meter-Interface/ Smart Metering]-Anbindungen, für die die Firmware allerdings angepasst selbst kompiliert werden muss. Michael hat sich (mit der Unterstützung aus der Tasmota-Community) daran gemacht und freundlicherweise die nötigen Anpassungen zur Verfügung gestellt: Folgendes muss in der Datei <code>tasmota/user_config_override.h</code> ergänzt werden: <source lang="C"> #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ #ifndef USE_SCRIPT #define USE_SCRIPT #endif #ifndef USE_SML_M #define USE_SML_M #endif #ifdef USE_RULES #undef USE_RULES #endif #ifndef SML_REPLACE_VARS #define SML_REPLACE_VARS #endif #ifndef USE_SML_SCRIPT_CMD #define USE_SML_SCRIPT_CMD #endif #ifndef SML_MAX_VARS #define SML_MAX_VARS 20 #endif #ifndef USE_SCRIPT_JSON_EXPORT #define USE_SCRIPT_JSON_EXPORT #endif #ifndef USE_SCRIPT_WEB_DISPLAY #define USE_SCRIPT_WEB_DISPLAY #endif </source> ==Konfiguration== Nach dem Flashen des Mikrocontrollers, was für fertige Builds auch über den Tasmotizer erfolgen kann, kann unter <code>Main-Menu -> Console -> Edit Script</code> das [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus Script ergänzt] werden. Mit dem Befehl <code>sensor53 d1</code> kann man den Header für die [https://tasmota.github.io/docs/Smart-Meter-Interface/#meter-metrics Meter Metrics] ermitteln und im Script entsprechend anpassen. Für die RemaSol B/2 sieht das wie folgt aus: <source> r="1,aa10005d101000010a67" coltemp=0 Byte1=0 Byte2=0 >S coltemp=sml[1] Byte1=coltemp>>8 Byte2=coltemp&0xff if Byte1==0x00 { coltemp=coltemp&0xff } if Byte1==0xff { coltemp=(coltemp-0x10000) } coltemp=coltemp*0.1 >B =>sensor53 r >M 1 +1,3,v,0,9600,Solar %r%vo0uw@1,KollektorBase,°C,kolbase,2 %r%vo0uw@10,KollektorOrg,°C,kolorg,2 %r%vo2uw@10,Speicher unten,°C,spu,1 %r%vo4uw@10,Speicher oben,°C,spo,1 %r%vo8ub@1,Pumpe,%%,pump,0 # >J ,"Calculated":{"kol":%coltemp%} >W Kollektor berechnet: {m} %coltemp% °C </source> Anmerkung: Hierbei handelt es sich um einen direkten Copy & Paste aus Michaels Script. Je nach Konfiguration der Anlage kann es Abweichungen geben. Um den Fragen zuvorzukommen - die Anpassung auf die Jeweilige Anlage beginnt in der ersten Zeile: <code> r="1,<span class="hb1">aa</span><span class="hb2">1000</span><span class="hb3">5d10</span><span class="hb4">10</span><span class="hb5">0001</span><span class="hb6">0a</span><span class="hb7">67</span>" </code> Die Farben entsprechen dem Beispiel von der [[VBus-Decoder#Protokoll|Artikelhauptseite]], kurzum: * <span class="hb1">aa</span>: Sync-Wort * <span class="hb2">1000</span>: Zieladresse * <span class="hb3">5d10</span>: Quelladresse * <span class="hb4">10</span>: Protokollversion * <span class="hb5">0001</span>: Befehl * <span class="hb6">0a</span>: Anzahl Nutzdatenframes * <span class="hb7">67</span>: Prüfsumme Die <span class="hb3">Quelladresse</span> kann in der [https://danielwippermann.github.io/resol-vbus/#/vsf VBus-Spezifikation nachgeschlagen werden]. Zu beachten ist hier die Endianness: was in der Doku als <code>0x1234</code> geschrieben ist, muss hier als <code>3412</code> angegeben werden. Anschließend muss man auf der [https://danielwippermann.github.io/resol-vbus/#/vsf oben genannten Seite] nach dem Command 0x0100 für den entsprechenden Regler suchen. Dazu am besten oben nach 0x0100 filtern und dann mit Strg+F die Quelladresse finden. Klickt man in der Zeile auf <code>Bytes</code> bekommt man die Länge der Nachricht, wobei man 1 addieren muss, da es sich um Offsets handelt. Beim RemaSol 1/2 (bzw. DeDietrich Sol Plus ER 709) ist der größte Offset 39, also 40 Bytes. Mit dem Wissen, dass ein Frame 4 Byte enthält, ergibt sich eine Länge von 10 Frames, was einem Hexadezimalwert von <span class="hb6">0x0A</span> entspricht. Nun muss man nur noch die Prüfsumme berechnen (oder durch Schnüffeln am UART ermitteln) Für die Feldzuordnung lohnt sich ein scharfer Blick und Vergleich der <code>Fields</code>-Seite für die [https://danielwippermann.github.io/resol-vbus/#/vsf/fields/00_0010_4221_10_0100 DeltaSol BS Plus] und dem Beispiel in der [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus dieses Reglers] in der Tasmota-Doku. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. Achtung: Es handelt sich um Version 0.1, auf der sich 3 kleine Fehler befinden, die sich allerdings mit Fädeldraht korrigieren lassen: ==Hotfix für v0.1== Um die Leiterkarte Version 0.1 korrekt nutzen zu können, sind bis zu 3 Fixes nötig: ===Bootloader-Schaltung=== Die Beschaltung der Transistoren ist teilweise falsch. Um dies zu korrigieren, müssen 3 Leiterbahnen aufgetrennt werden und die Verbindungen mit Fädeldraht neu hergestellt werden. Das Auftrennen kann je nach Geschmack mit einem kleinen Trennschleifer (Vulgo Dremel) oder einem Messer erfolgen. Statt der zwei Drähte zum unteren der beiden Widerstände kann der Widerstand (im 0603-Gehäuse) auch zwischen die beiden Pads am Transistor gelegt werden und damit ein Schnitt und eine Drahtverbindung gespart werden. <gallery> vbusesp_v01fix_transistor_rewire.png | Korrekturanleitung vbusesp_v01fix_transistor_prep1.jpg | mit dem Skalpell entfernt vbusesp_v01fix_transistor_prep2.jpg | mit dem Trennschleifer durchtrennt vbusesp_v01fix_transistor_done.jpg | Durchgeführte Korrektur </gallery> ===Beschaltung GPIO15 am ESP12=== Diese Korrektur ist nur relevant, wenn man ein ESP12-Modul einsetzt. Der Mikrocontroller startet nur, wenn GPIO15 über einen Pull-down mit Masse verbunden ist. Dazu sollte ein 10k-Widerstand zwischen diese beiden Pins, wie unten dargestellt, eingebaut werden: <gallery> vbusesp_v01fix_res.jpg | Durchgeführte Korrektur. Widerstand ist zweckvoll! </gallery> ===Pull-up an Q3=== Wird die Tx-Funktionalität verwendet, blockiert der als Pull-down eingesetzte R14 den Bus. Um dies zu berichtigen muss das linke Pad getrennt und mit und mit VBUS_3V3 verbunden werden: <gallery> vbusesp_v01fix_tx_pull.png | Korrekturanleitung </gallery> =Bekannte Probleme= ==Fehlerhafter Datenempfang== Carsten hat eine interessante Entdeckung bei seinem Aufbau gemacht, untersucht und dann auch gleich eine Lösung gefunden: <pre> Nachdem ich den VBus Dekoder programmiert hatte, ist mir aufgefallen, dass die gesamte Kommunikation sehr stark mit Bitfehlern behaft ist. Nur etwa ein Drittel der VBus Frames kamen unversehrt in der Software an; das Ende langer Pakete war so gut wie immer kaputt. Wenn ich einen FTDI USB Konverter hinter den Optokoppler gehängt habe, wurden die Daten fehlerfrei auf dem PC empfangen, also musste das Problem mit dem ESP zusammenhängen. Daher habe ich mir in den UART Treiber einen Debug-Pin eingebaut, der bei jedem Frame-Fehler mein DSO getriggert hat und das war dann zu sehen: </pre> <gallery> Vbusesp_carsten_rx_issue_1.png | Oszi-Screenshot mit defekter und korrekter Nachricht </gallery> <pre> Irgendwie hat der ESP RX Eingang unter bestimmten Umständen den Pin so stark nach VCC gezogen, dass die Pegel kaputt gegangen sind. Warum er das scheinbar nur manchmal macht, ist mir allerdings noch immer ein Rätsel. Dann weiter im Sourcecode gesucht, wo die Pin-Konfiguration während der Initialisierung des UART gemacht wird. Hier bin ich dann in der Datei 'core_esp8266_wiring_digital.cpp' fündig geworden: </pre> <gallery> Vbusesp_carsten_rx_issue_2.png | Codestelle des Fixes </gallery> <pre> Seitdem ich die Zeile 42 unschädlich gemacht habe, läuft die Kommunikation wie geschnitten Brot :-) Der Debug-Trigger hat auch nach mehreren Stunden nicht mehr zugeschlagen. Ich muss jetzt noch dazu sagen, dass ich die Software mit PlatformIO entwickele uns ich die Version 4.0.1 des ESP8266 Platform Package aktuell verwende. Das kann gut sein, dass es mit anderen IDEs und anderen/älteren Packages nicht passiert, weil der Pullup dort nicht eingeschaltet wird. </pre> Wer die Stelle im Repo sucht: [https://github.com/esp8266/Arduino/blob/master/cores/esp8266/core_esp8266_wiring_digital.cpp#L41 hier ist sie]. Ich bin zwar kein großer Freund, tief in Libs zu patchen, konnte aber nach einem Abend Erstkontakt mit den Tasmota-Sourcen keinen besseren Ort für eine Anpassung finden. Bleibt die Frage, warum der Pull-up aktiviert und deaktiviert wird - bei einer (kurzen) Suche ist mir im Code nichts aufgefallen. Kann natürlich sein, dass die CPU selbst das entsprechende Bit setzt/löscht, was aber merkwürdig wäre. Bleiben zwei Optionen: entweder selber nochmal forschen oder einen Issue in Github erstellen. =Downloads= * [[Datei:Vbusesp_0.2.zip]] EAGLE-Dateien Adapter v0.2 für den ESP8266 ==Archiv== * [[Datei:Vbusesp_0.1.zip]] EAGLE-Dateien Adapter v0.1 für den ESP8266 [[Kategorie:ESP8266]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 1de09c2bc15447cdabcc583ba45eac2ae378e109 VBus-Decoder 0 120 1830 1761 2023-01-17T20:48:50Z Chris 2 /* Hardware-Schnittstelle */ Sprache wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokoll erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Dies kann entweder mit Hilfe des Handbuchs in Erfahrung gebracht werden (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung vorhanden) oder durch Messung ermittelt werden: An den VBus-Klemmen sollte eine (zappelnde) Spannung von ca. 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/#/vsf Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> Achtung: Es ist empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2|1.2b]] nachzubauen. ==[[VBus-Decoder/Adapter für den ESP8266|Adapter für den ESP8266]]== Noch etwas kleiner als für den Raspberry Pi: Ein Adapter mit ESP8266-Modulen. <gallery> vbusesp_top.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] Oliver hat basierend auf dem Code von Nicki eine Schnittstelle zur [https://www.volkszaehler.org/ Volkszähler]-Middleware gebaut: <pre> Der Code nutzt die Resol-Decoder-Lib von Nicki, die ist auch mit dabei. In der config.py stellt man die Adresse der Middleware in seinem Netzwerk, sowie die UUID der Kanäle ein, damit man die Daten referenzieren kann. (Zum Test kann man auch simulierte Daten nutzen, oder die Ausgabe in ein File schreiben lassen) </pre> * [[Datei:Vbus_volkszaehler.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] dc2c01683f7373a4dffa4911aa06859dcc60ff5b 1837 1830 2023-02-22T21:01:32Z Chris 2 /* Adapter für den Raspberry Pi */ Abschnitt Versionen hinzugefügt wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokoll erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Dies kann entweder mit Hilfe des Handbuchs in Erfahrung gebracht werden (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung vorhanden) oder durch Messung ermittelt werden: An den VBus-Klemmen sollte eine (zappelnde) Spannung von ca. 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/#/vsf Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> ===Versionen=== * [[VBus-Decoder/Adapter für den Raspberry Pi v1.0|Version 1.0/1.1]]: Der erste Versuch - "never trust a x.0" * [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2|Version 1.2]]: Besser, aber noch nicht gut * '''[[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]]: Die beste Version, die man aktuell haben kann ;)''' ==[[VBus-Decoder/Adapter für den ESP8266|Adapter für den ESP8266]]== Noch etwas kleiner als für den Raspberry Pi: Ein Adapter mit ESP8266-Modulen. <gallery> vbusesp_top.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] Oliver hat basierend auf dem Code von Nicki eine Schnittstelle zur [https://www.volkszaehler.org/ Volkszähler]-Middleware gebaut: <pre> Der Code nutzt die Resol-Decoder-Lib von Nicki, die ist auch mit dabei. In der config.py stellt man die Adresse der Middleware in seinem Netzwerk, sowie die UUID der Kanäle ein, damit man die Daten referenzieren kann. (Zum Test kann man auch simulierte Daten nutzen, oder die Ausgabe in ein File schreiben lassen) </pre> * [[Datei:Vbus_volkszaehler.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] d614bea9bfd30e32e5220e48cce28154d53a9bc1 VBus-Decoder/Adapter für den Raspberry Pi v1.3 0 715 1831 1664 2023-02-22T20:37:27Z Chris 2 Hinweis zu JMP1 wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Who's perfect? Beim [[VBus-Decoder/Adapter_für_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] (und auch dem [[VBus-Decoder/Adapter_Nano|Nano]]) gibt es ein paar Unzulänglichkeiten, die jeweils ein Makeover der Leiterkarte erfordern. Da die Beliebtheit des Raspberry Pis deutlich größer als ein Arghduino für solche Anwendungen ist, gibt es hierfür zuerst (oder überhaupt) eine neue Version. Konkret handelt es sich um folgende Probleme, die mit der neuen Version behoben werden sollen: * Keine gestapelten Bauteile mehr * Hinreichend Eingangskapazität für mehr Zuverlässigkeit * Größere Bauteile zur einfacheren Bestückung * Rückkanal, um den Regler aktiv abfragen und parametrieren zu können =Änderungen= Aus dem MLCC-Kondensator wurde ein Elektrolyt, aktuell 100 µF, lässt sich bei Bedarf aber noch ein bisschen vergrößern. Dieser wird nun über einen Widerstand am Gleichrichter angebunden um den Ladestrom (und dadurch die Spannungseinbrüche auf dem Bus) zu verkleinern. Ob die Kombination aus 470 Ohm und 100 Mikrofarad gut ist, muss sich noch zeigen. Beim Spannungsregler ist der 3,3 V-Typ gekommen um zu bleiben. Dieser bietet neben dem etwas niedrigeren Preis den Vorteil, dass er auf der Eingangsseite einen größeren "Headroom" hat. Die Neudimensionierung der Spannungsteiler basiert auf den Berechnungen von [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]]. Als Bestückoption gibt es nun auch einen Jumper, mit dem die Versorgung des Komparators ausgewählt werden kann - sollten die Referenzspannungen nach dem 3,3 V-Regler doch zu knapp werden, kann die Eingangsspannung des LDO verwendet werden. Offen ist natürlich, ob der zu erwartende Ripple in die Suppe spuckt. Die diskreten Bauteile sind nun alle im 0805-Package, dadurch wurden weite Teile des Layouts umgeworfen. Wer möchte, kann natürlich auch welche im 0603-Package (oder mit ein bisschen Wollen sollte auch 1206 gehen) auf die Footprints packen. Gänzlich neu ist der Rückkanal, die Dimensionierung dessen Bauteile erfolgte mit dem feuchten Finger in den Wind gehalten. Es ist eigentlich nichts besonderes zu erwarten, bei Bedarf kann allerdings einfach mit den Bauteilen gespielt werden. Die Änderungen kommen allerdings mit ein paar Kompromissen: * Die Leiterkarte wurde ein bisschen größer * Die Power-LED für den VBus ist rausgefallen (kein Platz, unnötiger Verbraucher) * Bei der Nutzung des Rückkanals ist... ** die Leiterkarte auf dem Pi Zero nur mit "Überhang" verwendbar ** keine galvanische Trennung möglich <gallery> Vbuspi_1.3_assy_sch.png | Schaltplan Vbuspi_1.3_assy_brd.png | Layout </gallery> =BOM= <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 15k || R0805 || RND 0805 1 15K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_opto_sch.png | Bestückungsplan für optoisolierte Variante </gallery> </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X3 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 3 || Q1, Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_direct_sch.png | Bestückungsplan für unisolierte Variante </gallery> </tab> </tabs> =Hinweise= * '''Bitte nur die Bauteile bestücken, die in der BOM für die jeweilige Variante angegeben sind. Mehr hilft nicht mehr, sondern kann zu Fehlfunktionen führen.''' * R14 in der Direktvariante sollte nicht bestückt werden oder zumindest in Pull-up-Konfiguration umgebaut werden. Sonst kann (und wird) es passieren, dass der VBus bei nicht angeschlossenem Tx dauerhaft kurzgeschlossen wird. (Danke an Heiko für den Hinweis!) * R1 sollte einen Wert ab ca. 12k haben, damit der Low-Pegel auch wirklich 0 erreicht. * Aktuell ist nur die optoisolierte Version getestet * selbst bei "nur" 1,2 mm dickem FR4 würde ich nicht empfehlen, die Leiterkarte an den perforierten Kanten zu brechen. Besser sägen oder mit einer Trennscheibe arbeiten. * Nicht vergessen, JMP1 zu bestücken oder zumindest die entsprechende Lötbrücke zu setzen. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbuspi_1.3.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] cc3d00dd0feb3a43e36761502e2991bd49a0e43a 1838 1831 2023-02-22T21:15:59Z Chris 2 /* Änderungen */ Link korrigiert wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Who's perfect? Beim [[VBus-Decoder/Adapter_für_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] (und auch dem [[VBus-Decoder/Adapter_Nano|Nano]]) gibt es ein paar Unzulänglichkeiten, die jeweils ein Makeover der Leiterkarte erfordern. Da die Beliebtheit des Raspberry Pis deutlich größer als ein Arghduino für solche Anwendungen ist, gibt es hierfür zuerst (oder überhaupt) eine neue Version. Konkret handelt es sich um folgende Probleme, die mit der neuen Version behoben werden sollen: * Keine gestapelten Bauteile mehr * Hinreichend Eingangskapazität für mehr Zuverlässigkeit * Größere Bauteile zur einfacheren Bestückung * Rückkanal, um den Regler aktiv abfragen und parametrieren zu können =Änderungen= Aus dem MLCC-Kondensator wurde ein Elektrolyt, aktuell 100 µF, lässt sich bei Bedarf aber noch ein bisschen vergrößern. Dieser wird nun über einen Widerstand am Gleichrichter angebunden um den Ladestrom (und dadurch die Spannungseinbrüche auf dem Bus) zu verkleinern. Ob die Kombination aus 470 Ohm und 100 Mikrofarad gut ist, muss sich noch zeigen. Beim Spannungsregler ist der 3,3 V-Typ gekommen um zu bleiben. Dieser bietet neben dem etwas niedrigeren Preis den Vorteil, dass er auf der Eingangsseite einen größeren "Headroom" hat. Die Neudimensionierung der Spannungsteiler basiert auf den Berechnungen von [[Adapter_für_den_Raspberry_Pi_v1.2#Die Enttäuschung - Teil 2| Version 1.2b]]. Als Bestückoption gibt es nun auch einen Jumper, mit dem die Versorgung des Komparators ausgewählt werden kann - sollten die Referenzspannungen nach dem 3,3 V-Regler doch zu knapp werden, kann die Eingangsspannung des LDO verwendet werden. Offen ist natürlich, ob der zu erwartende Ripple in die Suppe spuckt. Die diskreten Bauteile sind nun alle im 0805-Package, dadurch wurden weite Teile des Layouts umgeworfen. Wer möchte, kann natürlich auch welche im 0603-Package (oder mit ein bisschen Wollen sollte auch 1206 gehen) auf die Footprints packen. Gänzlich neu ist der Rückkanal, die Dimensionierung dessen Bauteile erfolgte mit dem feuchten Finger in den Wind gehalten. Es ist eigentlich nichts besonderes zu erwarten, bei Bedarf kann allerdings einfach mit den Bauteilen gespielt werden. Die Änderungen kommen allerdings mit ein paar Kompromissen: * Die Leiterkarte wurde ein bisschen größer * Die Power-LED für den VBus ist rausgefallen (kein Platz, unnötiger Verbraucher) * Bei der Nutzung des Rückkanals ist... ** die Leiterkarte auf dem Pi Zero nur mit "Überhang" verwendbar ** keine galvanische Trennung möglich <gallery> Vbuspi_1.3_assy_sch.png | Schaltplan Vbuspi_1.3_assy_brd.png | Layout </gallery> =BOM= <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 15k || R0805 || RND 0805 1 15K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_opto_sch.png | Bestückungsplan für optoisolierte Variante </gallery> </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X3 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 3 || Q1, Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_direct_sch.png | Bestückungsplan für unisolierte Variante </gallery> </tab> </tabs> =Hinweise= * '''Bitte nur die Bauteile bestücken, die in der BOM für die jeweilige Variante angegeben sind. Mehr hilft nicht mehr, sondern kann zu Fehlfunktionen führen.''' * R14 in der Direktvariante sollte nicht bestückt werden oder zumindest in Pull-up-Konfiguration umgebaut werden. Sonst kann (und wird) es passieren, dass der VBus bei nicht angeschlossenem Tx dauerhaft kurzgeschlossen wird. (Danke an Heiko für den Hinweis!) * R1 sollte einen Wert ab ca. 12k haben, damit der Low-Pegel auch wirklich 0 erreicht. * Aktuell ist nur die optoisolierte Version getestet * selbst bei "nur" 1,2 mm dickem FR4 würde ich nicht empfehlen, die Leiterkarte an den perforierten Kanten zu brechen. Besser sägen oder mit einer Trennscheibe arbeiten. * Nicht vergessen, JMP1 zu bestücken oder zumindest die entsprechende Lötbrücke zu setzen. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbuspi_1.3.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 16153cda98b966ed595c8a1017a769da668ea697 VBus-Decoder/Adapter für den Raspberry Pi v1.2 0 814 1832 2023-02-22T20:43:01Z Chris 2 Seite erstellt wikitext text/x-wiki =Kostenreduzierte Variante/v1.2= Eine der Verbesserungspotenziale war, die Kosten durch einen TS 5205 CX533 etwas zu reduzieren. ==Die Enttäuschung== '''Achtung: es gibt noch eine [[#Die Enttäuschung - Teil 2|weitere Enttäuschung]].''' Um einer Enttäuschung beim Aufbau zu entgehen, ging der erste Schritt in die Simulation - die vielversprechend war. Bauteile auf die Leiterkarte und ab zum Solarregler. Ergebnis bei der Messung: Mist. Die Spannung am Regler-Ausgang zappelt und verzieht dadurch die Schwellenwerte, die LED auf der RPi-Seite flackert zwar, der Low-Spannungspegel ist aber so hoch, dass der SoC garantiert nichts mehr damit anfangen kann. Im ersten Schritt kommt also die LED runter. Aber zunächst zum Regler: <gallery> vbuspi3v3_vout_ripple.png | Ch1: AC-Anteil der 3,3 V-Versorgung (IC1.5), Ch2: Ch2: AC-Anteil der Komparator-Referenz (IC4.5) vbuspi3v3_schwelle_orig.png | Schwellenwerte des Komparators - Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5), Ch3: Ausgang am Optokoppler (IC4.1) </gallery> Wie in den Screenshots zu sehen ist, zappelt die Referenz ganz ordentlich, wobei das nur die halbe Wahrheit ist: Die Kapazität der Oszi-Probe verändert das Signal. Ohne Probe 2 sieht man auf Kanal 2 einen doppelten Puls. Das darf nicht sein. Die Peaks im 20 ms-Abstand sind vermutlich Artefakte vom Bus des [[ECL-Bus-Decoder|Heizungsreglers]], der seine Daten auf ein 50 Hz-Rechtecksignal moduliert und in meinem Setup auf einem benachbarten Adernpaar in der gleichen Leitung liegt. Auch wenn ich mir nicht sicher bin, ob der Spannungseinbruch am Regler durch die zu geringe Ausgangskapazität oder durch eine Instabilität entsteht, nicht ganz unschuldig daran ist sicher der etwas höhere Strom des Optokopplers. Mit einem deutlich größeren Ausgangskondensator am Regler entspannt sich die Lage ein gutes Stück, nicht getestet habe ich allerdings das Verhalten, wenn ein C am Bypass-Pins des Reglers angeschlossen ist. Aber einen guten Punkt kann ich dem Bild abgewinnen: die stationären Werte der Schwellenspannungen passen (innerhalb der recht großen Messtoleranzen) ziemlich gut. Auch wenn mit der deutlich besseren Glättung das Verhalten fast gut ist, ist es eben nur fast gut. Um das Zittern der Referenz am Komparator zu vermeiden, bekommt R4 einen Freund: ein 100 pF-Kondensator wird Huckepack aufgelötet. Mit dem zusätzlichen Kondensator sieht es nun wie folgt aus: <gallery> vbuspi3v3_100p_schwelle1.png | Schwellenverlauf des Komparators Ch1: Eingang am Komparator (IC4.6), Ch2: Komparator-Referenz (IC4.5) vbuspi3v3_100p_schwelle2.png | Schaltschwelle des Komparators im Überblick, Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle3.png | Schaltschwelle des Komparators im Überblick (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle4.png | Schaltschwelle des Komparators, fallende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) vbuspi3v3_100p_schwelle5.png | Schaltschwelle des Komparators, steigende Flanke (mit Cursor) Ch1: Eingang am Komparator (IC4.6), Ch2: Treiberausgang (IC4.1) </gallery> Wichtig ist nach wie vor, dass die Verzögerungen über den Optokoppler halbwegs symmetrisch sind, da es UART-Interfaces aus dem Tritt bringen kann. <gallery> vbuspi3v3_delay1.png | Übersicht über ein Datenbit, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay2.png | Verzögerung bei fallender Flanke: 2,11 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler vbuspi3v3_delay3.png | Verzögerung bei steigender Flanke: 1,33 µs, Ch1: Kathode des Optokoppler (OK1.3), Ch2: Kollektor des Optokoppler </gallery> Es gibt also eine Asymmetrie von 0,78 µs, bei einer idealen Bitzeit von ca. 104 µs sind das 0,75 %. Nicht der Rede wert. ==Die (vermeintliche) Lösung== Probleme sind dafür da, gelöst zu werden. Zwar kann die Leiterkarte der Version 1.0 so umgebaut werden, dass sie auch mit 3,3 V funktioniert, indem folgende Änderungen angewendet werden: * R3: 15k * R4: 33k * R6: 15k * C3: 4,7 µF-Kondensator * Auf R4 einen 100 pF-Kondensator löten * LED3 und R28: weglassen * IC1: TS5205CX533 Im Grunde kann die untenstehende BOM auch für Version 1.0 der Leiterkarte verwendet werden. Aber zumindest mein Anspruch ist etwas größer, also gibt es eine neue Revision der Leiterkarte: <gallery> vbuspi3v3_1.2_sch.png | Schaltplan Vbuspi_1.2_assy_top.png | Bestückungsplan Oberseite Vbuspi_1.2_assy_bot.png | Bestückungsplan Unterseite </gallery> Die BOM ist nun ein bisschen günstiger: {| class="wikitable" ! Menge|| Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || X7R 0603FCG 100P |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 2 || R3, R6 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R4 || 33k || R0603 || RND 0603 1 33K |- | 1 || C7 || 470p || C0603 || X7R-G0603 470P |- | 1 || C3 || 4u7 || C0603 || KEM X5R0603 4,7U |- | 1 || R9 || 680 || R0603 || RND 0603 1 680 |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || or || CHIP-LED0603 || LED EL 0603 OR |} ==Die Enttäuschung - Teil 2== Stefan schickte eine Mail mit einen sehr guten Verbesserungsvorschlag bzw. vielmehr Hinweis auf Fehler: <pre> Ich würde an deiner Stelle bei der 3,3V Schaltung den Spannungsteiler R8/R5 anpassen. An dessen Eingang können ~7V anliegen womit der OP dann 3,5V an seinem Eingang hat. Das ist bei 3,3V Versorgungsspannung etwas über der Spezifikation des verwendeten OPs. </pre> Das ist absolut richtig, die Spannung ist außerhalb der Spec. Der Fehler hat sich mit an Sicherheit grenzender Wahrscheinlichkeit eingeschlichen, weil beim Neudimensionieren der Schaltung nur die Teile berücksichtigt wurden, die direkt an +3V3 hängen. Schaut man noch etwas genauer ins Datenblatt entdeckt man, dass die Eingänge des LM393 für eine korrekte Funktion einen gewissen Abstand zu V+ haben müssen. Bei der Variante von TI sind das VDD - 1,5 V. Ok, das ist natürlich Mist. Aber beherrschbarer. Im Prinzip müssen nur die Widerstände für die Spannungsteiler neu berechnet werden. Jetzt kann man es sich natürlich einfach machen und die naheliegendsten Werte aus der E24-Reihe nehmen. Selbst für gut ausgestattete Widerstandslager zu Hause würde das eine Bestellung bei den üblichen Verdächtigen bedeuten. Dann hat man meistens noch die vermutlich selten genutzten Wert-Überreste in einer Schublade liegen und das Bestücken ist fehleranfälliger. Uncool. Also warum nicht so lange mit den Bauteilwerten jonglieren, bis es eine gute Kombination gibt? Kann man manuell machen, ist aber eher mühsam. Geht auch mit Excel, ist aber auch nicht das beste Tool dafür. Ob JavaScript so wirklich dafür geeignet ist, sei mal dahingestellt - dafür spricht allerdings, dass mittlerweile fast jedes Endgerät mit Farbdisplay eine passende Laufzeitumgebung installiert hat. Herausgekommen ist dieser [//hobbyelektronik.org/tools/komparator/ schlichte Rechner]. Zahlen eingeben und los geht's: {| class="wikitable" ! Bezeichnung || Wert || Kommentar |- | Versorgungsspannung Komparator || 3,3 V || |- | Maximale Eingangsspannung Komparator || 1,8 V || (3,3 - 1,5) V |- | Maximale Signalspannung || 6,8 V || (8,2 - 1,4) V |- | Obere Schwelle || 4,5 V || aus der VBus-Spec |- | Untere Schwelle || 4,0 V || aus der VBus-Spec |- |} Aktuell werden Widerstände aus der E6- und (damit es ein bisschen Mehr Auswahl gibt) E12-Reihe für die Bauteilsuche genutzt. Für die eingegebenen Werte ergibt sich eine schöne Kombination aus der E6-Reihe, die nur drei unterschiedliche Werte benötigt: {| class="wikitable" ! Referenz || Wert |- | R8 || 15 k |- | R5 || 4,7 k |- | R3 || 4,7 k |- | R4 || 2,2 k |- | R2 || 15 k |} Zur Gegenprobe - der Spannungsteiler gibt folgende Spannung aus: <math>(\textrm{8,2 V} - \textrm{1,4 V}) \cdot \frac{\textrm{4,7 k}}{\textrm{4,7 k} + \textrm{15 k}} = \textrm{6,8 V} \cdot \frac{\textrm{4,7}}{\textrm{19,7}} = \textrm{1,62 V}</math> Da ist noch gut Luft zu den Maximal 1,8 V - rechnet man rück, dürfte der Spannungsabfall über den Gleichrichter bis auf 0,65 (für beide Dioden) fallen, um auf eine Eingangsspannung von über 1,8 V am Komparator zu kommen Der Kondensator für den Tiefpass kann übrigens gleich bleiben. Die Grenzfrequenz steigt zwar ein wenig, der Wert ist jedoch weniger kritisch. Daraus ergibt sich folgender Schaltplan: <gallery> Vbuspi_1.2b_assy_sch.png|Schaltplan Version 1.2b </gallery> Die aktualisierte BOM lautet wie folgt: <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2* || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 6k8 || R0603 || RND 0603 1 6,8K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 1 || C2 || 100n || C0603 || X7R-G0603 100N |- | 1 || C6 || 100p || C0603 || NPO-G0603 100P |- | 2* || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 3 || R2, R6, R8 || 15k || R0603 || RND 0603 1 15K |- | 1 || X1/X4 || 1751248 || 1751248 || AKL 059-02 |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 2 || R4, R7 || 2k2 || R0603 || RND 0603 1 2,2K |- | 1 || C3 || 3u3/10V || C0603 || X5R-G0603 3,3/10 |- | 2 || R3, R5 || 4k7 || R0603 || RND 0603 1 4,7K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART_CONDENSED || RPI_UNIV_UART || RND 205-00654 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> <nowiki>*)</nowiki> am besten zwei verwenden und stapeln, damit der Schaltung bei längeren Nachrichten die Puste nicht ausgeht - siehe unten Damit sollte nun der Komparator glücklich sein. Auch in der Simulation in LTspice passen die Schwellen und das Verhalten der Schaltung. Hierzu hatte Stefan folgende Anmerkung: <pre> Nicht gefallen tut mir der C6 von 100pF. Dadurch wird zwar die Referenz stabiler aber die Schwellenumschaltung beim Pegelwechsel wird langsamer. Damit reduziert sich die Störfestigkeit des Eingangssignals. Ich hätte es aber vermutlich auch so gemacht. </pre> Ja, das ist richtig - und auch ich war/bin über den Kondensator nicht so richtig glücklich. Das Bauteil ist meiner Meinung allerdings ein sehr einfacher und effektiver Weg, das beschriebene Problem - besonders im bereits existierenden Design - einfach zu umgehen. Da die Versorgung nicht 100 %ig stabil war, hatte er noch folgenden Ratschlag: <pre> Noch eine Anmerkung zu deiner Kostenreduktion mit dem TS5205 CX533. Ich vermute dass der Ausgangskondensator (C3) nicht passt (ESR zu hoch). LowDrop Regler sind bei zu hohem ESR instabil. Manchmal hilft ein 2ter Kondensator parallel zu C3 (so 10nF bis 100nF) um den Regler stabil zu bekommen. </pre> Was ich versucht habe aber nicht zum gewünschten Erfolg verhalf. Das Problem ist vermutlich eher, dass die Schaltung bei aktivem Optokoppler gänzlich aus den Bulk-Kondensatoren gespeist werden müssen. Da hilft nur mehr Kapazität am Eingang, weswegen als Workaround C5 "aufgedoppelt" werden sollte (Stapeln zweier Kondensatoren). Das ist zwar nicht so richtig schön, aber sollte in den meisten Fällen helfen. Aufgrund der verschiedenen Unzulänglichkeiten - und um den bei manchen Reglern erforderlichen Rückkanal zu haben - gibt es eine verbesserte Version der Hardware: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] =Downloads= * [[Datei:vbus_pi_v1.2_3v3.zip]] EAGLE-Dateien und LTspace-Simulationsdaten für die 3,3 V-Version des VBus-Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 3cb81c42103899ea3a3f4b080f23028deb2d0cf6 VBus-Decoder/Adapter für den Raspberry Pi 0 706 1833 1657 2023-02-22T20:43:49Z Chris 2 Version 1.2 ausgelagert wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' '''Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2#Die Enttäuschung - Teil 2|1.2b]] nachzubauen.''' =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8* (siehe unten) || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: * Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. * Mit R1 = 6,8k kann der Low-Pegel für die vom Raspberry Pi verwendeten 3,3 V zu hoch sein. Besser einen Wert ab 12k verwenden =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Leiterkarten= Sorry, aktuell gibt es keine mehr. =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] aa569745fa8b2682a615fea3fc40fe5dbca6373d 1835 1833 2023-02-22T20:58:28Z Chris 2 Abschnitt "Einrichtung am Raspberry Pi" hinzugefügt wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' '''Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2#Die Enttäuschung - Teil 2|1.2b]] nachzubauen.''' =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. =Versionen= * [[VBus-Decoder/Adapter für den Raspberry Pi v1.0|Version 1.0/1.1]]: Der erste Versuch - "never trust a x.0" * [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2|Version 1.2]]: Besser, aber noch nicht gut * [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3]]: Die beste Version, die man aktuell haben kann ;) =Einrichtung am Raspberry Pi= ==Raspbian== Damit der UART unter Raspbian verwendet werden kann und es keine Kollision mit der Konsole gibt, muss diese in <code>/boot/cmdline.txt</code> deaktiviert werden. Dazu mittels <code>sudo nano /boot/cmdline.txt</code> die Datei öffnen und folgende Zeile löschen: <pre> console=serial0, 115200 </pre> ==Debian Bookworm== Verwendet man Debian Bookworm, muss in <code>/boot/firmware/config.txt</code> enable_uart deaktiviert werden, also folgendes gesetzt werden: <pre> enable_uart=0 </pre> in <code>/boot/firmware/cmdline.txt</code> muss folgende Zeile entfernt werden (überlebt Kernel-Updates nicht): <pre> console=tty0 root=LABEL=RASPIROOT rw fsck.repair=yes net.ifnames=0 rootwait </pre> Abschließend muss noch folgende Zeile zu <code>/etc/default/raspi-firmware</code> hinzugefügt werden: <pre> CONSOLES="tty0" </pre> Vielen Dank an Jörg für den Hinweis! =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 0b93f30c81eb9a4f10c63281a61f084b55f200a5 1836 1835 2023-02-22T20:58:58Z Chris 2 /* Versionen */ Linktext korrigiert wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' '''Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2#Die Enttäuschung - Teil 2|1.2b]] nachzubauen.''' =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. =Versionen= * [[VBus-Decoder/Adapter für den Raspberry Pi v1.0|Version 1.0/1.1]]: Der erste Versuch - "never trust a x.0" * [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2|Version 1.2]]: Besser, aber noch nicht gut * [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]]: Die beste Version, die man aktuell haben kann ;) =Einrichtung am Raspberry Pi= ==Raspbian== Damit der UART unter Raspbian verwendet werden kann und es keine Kollision mit der Konsole gibt, muss diese in <code>/boot/cmdline.txt</code> deaktiviert werden. Dazu mittels <code>sudo nano /boot/cmdline.txt</code> die Datei öffnen und folgende Zeile löschen: <pre> console=serial0, 115200 </pre> ==Debian Bookworm== Verwendet man Debian Bookworm, muss in <code>/boot/firmware/config.txt</code> enable_uart deaktiviert werden, also folgendes gesetzt werden: <pre> enable_uart=0 </pre> in <code>/boot/firmware/cmdline.txt</code> muss folgende Zeile entfernt werden (überlebt Kernel-Updates nicht): <pre> console=tty0 root=LABEL=RASPIROOT rw fsck.repair=yes net.ifnames=0 rootwait </pre> Abschließend muss noch folgende Zeile zu <code>/etc/default/raspi-firmware</code> hinzugefügt werden: <pre> CONSOLES="tty0" </pre> Vielen Dank an Jörg für den Hinweis! =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 5b2d7349df0da2bcb4fcdd8842396782ea6eb835 1839 1836 2023-02-24T21:13:33Z Chris 2 /* Debian Bookworm */ korrigiert wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' '''Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2#Die Enttäuschung - Teil 2|1.2b]] nachzubauen.''' =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. =Versionen= * [[VBus-Decoder/Adapter für den Raspberry Pi v1.0|Version 1.0/1.1]]: Der erste Versuch - "never trust a x.0" * [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2|Version 1.2]]: Besser, aber noch nicht gut * [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]]: Die beste Version, die man aktuell haben kann ;) =Einrichtung am Raspberry Pi= ==Raspbian== Damit der UART unter Raspbian verwendet werden kann und es keine Kollision mit der Konsole gibt, muss diese in <code>/boot/cmdline.txt</code> deaktiviert werden. Dazu mittels <code>sudo nano /boot/cmdline.txt</code> die Datei öffnen und folgende Zeile löschen: <pre> console=serial0, 115200 </pre> ==Debian Bookworm== Verwendet man Debian Bookworm, muss in <code>/boot/firmware/config.txt</code> enable_uart deaktiviert werden, also folgendes gesetzt werden: <pre> enable_uart=0 </pre> In <code>/boot/firmware/cmdline.txt</code> muss der markierte Teil entfernt werden (überlebt Kernel-Updates nicht): <code> <span style="color: lightgrey">console=tty0</span> <span style="background-color: #FFC9C9; text-decoration: line-through;">console=ttyS1,115200</span> <span style="color: lightgrey">root=LABEL=RASPIROOT rw fsck.repair=yes net.ifnames=0 rootwait</span> </code> Alternativ kann man wie folgt vorgehen: Die Datei <code>/etc/default/raspi-firmware</code> wird beim Kernel Update verwendet, um die Datei <code>/boot/firmware/cmdline.txt</code> neu zu schreiben. Hier muss die Konsole fest auf (nur) "tty0" gesetzt werden: <pre> CONSOLES="tty0" </pre> Nach einem Kernel Update oder dem Ausführung von <code>update-initramfs -k all -u</code> (dauert mind. 40 Sekunden) sollte sich in der Datei <code>/boot/firmware/cmdline.txt</code> kein "ttyS1" mehr wiederfinden (Beispiel): <pre> console=tty0 root=LABEL=RASPIROOT rw fsck.repair=yes net.ifnames=0 rootwait </pre> Vielen Dank an Jörg für den Hinweis! =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 9892eb4d2f317b306b7dfbf30b5386ca8599b1c6 1840 1839 2023-02-24T21:28:13Z Chris 2 Farbton wikitext text/x-wiki ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' '''Achtung: Diese Hardware ist etwas unter die Räder gekommen, es gibt ein paar Unzulänglichkeiten. Deshalb ist es empfehlenswert, entweder [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]] oder zumindest [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2#Die Enttäuschung - Teil 2|1.2b]] nachzubauen.''' =Einleitung= Die meisten werden ihre Solaranlage vermutlich über den Raspberry Pi (oder kompatbile) ins Netz bringen wollen. Deshalb gibt es nun auch eine Variante für den Kleincomputer. Damit sie sowohl am B-Modell als auch auf den Zero montiert werden können, ist sie trennbar. Damit der untere Teil im Fall der Verwendung am Zero nicht im Müll landen muss, befindet sich auf der Unterseite ein Punktraster im Abstand von 1,27 mm. Dort lässt sich gut mit SMD-Bauteilen (z. B. im 0603- oder SO-Gehäuse) basteln oder zumindest das Löten üben. =Versionen= * [[VBus-Decoder/Adapter für den Raspberry Pi v1.0|Version 1.0/1.1]]: Der erste Versuch - "never trust a x.0" * [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2|Version 1.2]]: Besser, aber noch nicht gut * [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]]: Die beste Version, die man aktuell haben kann ;) =Einrichtung am Raspberry Pi= ==Raspbian== Damit der UART unter Raspbian verwendet werden kann und es keine Kollision mit der Konsole gibt, muss diese in <code>/boot/cmdline.txt</code> deaktiviert werden. Dazu mittels <code>sudo nano /boot/cmdline.txt</code> die Datei öffnen und folgende Zeile löschen: <pre> console=serial0, 115200 </pre> ==Debian Bookworm== Verwendet man Debian Bookworm, muss in <code>/boot/firmware/config.txt</code> enable_uart deaktiviert werden, also folgendes gesetzt werden: <pre> enable_uart=0 </pre> In <code>/boot/firmware/cmdline.txt</code> muss der markierte Teil entfernt werden (überlebt Kernel-Updates nicht): <code> <span style="color: grey">console=tty0</span> <span style="background-color: #FFC9C9; text-decoration: line-through;">console=ttyS1,115200</span> <span style="color: grey">root=LABEL=RASPIROOT rw fsck.repair=yes net.ifnames=0 rootwait</span> </code> Alternativ kann man wie folgt vorgehen: Die Datei <code>/etc/default/raspi-firmware</code> wird beim Kernel Update verwendet, um die Datei <code>/boot/firmware/cmdline.txt</code> neu zu schreiben. Hier muss die Konsole fest auf (nur) "tty0" gesetzt werden: <pre> CONSOLES="tty0" </pre> Nach einem Kernel Update oder dem Ausführung von <code>update-initramfs -k all -u</code> (dauert mind. 40 Sekunden) sollte sich in der Datei <code>/boot/firmware/cmdline.txt</code> kein "ttyS1" mehr wiederfinden (Beispiel): <pre> console=tty0 root=LABEL=RASPIROOT rw fsck.repair=yes net.ifnames=0 rootwait </pre> Vielen Dank an Jörg für den Hinweis! =Weiteres= Die [[3D-Druck-Sammelsurium#Raspberry_Pi_Zero_Spacer|Raspberry Pi Zero Spacer]] passen auch hier. [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] db8f296d24f3a16e169a57be23d467084a5a016a VBus-Decoder/Adapter für den Raspberry Pi v1.0 0 815 1834 2023-02-22T20:46:20Z Chris 2 Die Seite wurde neu angelegt: „Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher…“ wikitext text/x-wiki Es war angedacht, die Leiterkarte abreißbar zu machen, was zumindest bei Version 1.0 nicht wirklich gut klappte. Bei Version 1.1 sind die Löcher etwas näher beieinander, daher sollte es hier besser funktionieren. Wer eine 1.0 bekommt und sie am Zero betreiben will, sollte sie auf jeden Fall mit der Säge kürzen. <gallery> Vbuspi 1.1 assy sch.png|Schaltplan Vbuspi 1.1 assy top.png|Bestückungsplan Oberseite Vbuspi 1.1 assy bot.png|Bestückungsplan Unterseite Vbuspi 1.0 bare.jpg|Unbestückte Leiterkarte (v1.0) Vbuspi 1.1 assy zero.jpg|Bestücktge Leiterkarte auf einem Raspberry Pi Zero W </gallery> {| class="wikitable" ! Menge || Referenz || Wert || Package || Reichelt Bestellcode |- | 2 || R10, R11 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C3 || 100n || C0603 || X7R-G0603 100N |- | 3 || R5, R7, R8 || 10k || R0603 || RND 0603 1 10K |- | 1 || C5 || 10u/16V || C1206 || KEM X7R1206 10U |- | 1 || R4 || 15k || R0603 || RND 0603 1 15K |- | 2 || X1, X4 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R3, R6 || 18k || R0603 || RND 0603 1 18K |- | 3 || R9, R24, R28 || 1k || R0603 || RND 0603 1 1,0K |- | 1 || C1 || 680p || C0603 || X7R 0603 CG 680P |- | 1 || C4 || 1n || C0603 || X7R-G0603 1,0N |- | 1 || R1 || 6k8* (siehe unten) || R0603 || RND 0603 1 6,8K |- | 1 || R2 || 68k || R0603 || RND 0603 1 68K |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || IC1 || LP2985IM5-5.0 || SOT23-DBV || LP 2985 IM5-5.0 |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || || RPI_UNIV_UART || RND 205-00654 |- | 1 || LED1 || gn || CHIP-LED0603 || LED EL 0603 GR1 |- | 1 || LED3 || nicht bestücken! || siehe Fehler || - |} Achtung: * Die Vorwiderstände für die LEDs sind nicht getestet, die Bauteile in der BOM sind nur exemplarisch. * Mit R1 = 6,8k kann der Low-Pegel für die vom Raspberry Pi verwendeten 3,3 V zu hoch sein. Besser einen Wert ab 12k verwenden =Fehler & Verbesserungen= Diese betreffen nur Leiterkarten der Version 1.0, in der noch nicht physisch vorhandenen 1.1 sollten sie behoben sein, eine Überprüfung steht aber noch aus. * Leiterkarte ist nicht durch Abbrechen teilbar * Das mittlere Montageloch ist um 0,5 mm nach unten versetzt * Links oben ist die Leiterkarte nicht abgerundet (in den Gerber-Daten korrekt, in der Fertigung schief gegangen) * Die Schaltung selbst ist größtenteils durch den Nano erfolgreich getestet, der Einfluss der LEDs jedoch nicht * Mit bestückter LED3 werden die Low-Pegel des Optokopplers so weit nach oben gezogen, dass diese vom Raspi nicht mehr erkannt werden. Entweder nicht bestücken (R28 dito) oder einen FET (siehe Version 1.2) einfädeln. =Downloads= * [[Datei:Vbus_pi.zip]] EAGLE-Dateien Adapter für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 33f42fc435c9132fe2b991ac75cdad51fb3ba072 Datei:Ff rebooter router leds detail.jpg 6 816 1841 2023-04-11T20:13:32Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ff rebooter xiaomi start.png 6 817 1842 2023-04-11T20:13:32Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ff rebooter sch.png 6 818 1843 2023-04-11T20:13:32Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ff rebooter router leds beschaltung.jpg 6 819 1844 2023-04-11T20:13:33Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ff rebooter fsm.png 6 820 1845 2023-04-11T20:13:33Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ff rebooter router leds.jpg 6 821 1846 2023-04-11T20:13:33Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ff rebooter pcb.png 6 822 1847 2023-04-11T20:13:33Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ff rebooter pcb bot.jpg 6 823 1848 2023-04-11T20:13:33Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ff rebooter xiaomi input.jpg 6 824 1849 2023-04-11T20:13:33Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ff rebooter pcb top.jpg 6 825 1850 2023-04-11T20:13:33Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ff rebooter xiaomi einbau.jpg 6 826 1851 2023-04-11T20:13:33Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Ff rebooter xiaomi start.mp4 6 827 1852 2023-04-11T20:13:50Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Freifunk-Rebooter 0 828 1853 2023-04-11T20:15:35Z Chris 2 Seite erstellt wikitext text/x-wiki =Ausgangssituation= In unseren Flüchtlingsunterkünften stehen mehrere Xiaomi Mi Router 4A Gigabit Edition, die mit der Freifunk-München-Firmware bespielt sind. Wer Freifunk nicht kennt, kann und sollte am besten sich in der [[wpde:Freifunk|Wikipedia]] informieren. Was am Anfang noch recht gut funktionierte, wurde mit der Zeit immer instabiler. Ein Cronjob zum nächtlichen Neustart brachte zwar Besserung, aber nach ein paar Tagen gingen die Router in eine Bootloop. Um den Fehler besser zu verstehen, wurde zeitweise ein [https://hobbyelektronik.org/b/2022/10/uart-logging-mit-linux/ Raspberry Pi zum Protokollieren] abgestellt. Als jemand, der von Linux nur rudimentäres Wissen besitzt, sahen die Meldungen so aus, als könne der SoC einen der WLAN-Chips nicht mehr initialisieren und schoss sich ins Nirwana. Blöd: ein Reboot richtet das nicht, Dokumentation für die Chips hängt wohl hinter der NDA-Mauer und einen hard-reset scheint es nicht zu geben. Nach einem kurzen Austausch im Chat der Freifunker gab es ein Ticket bei OpenWRT und nach einigen paar Tagen auch eine Experimental-Firmware, die den Fehler beheben sollte. Sollte. Ein paar Tage später stand bei Grafana für die Knoten wieder "no data", dafür gab es Klagen aus der Unterkunft. Einer der Router steht hinter für die dauerhaft verschlossener Tür, der andere in einem Zimmer dessen Bewohner auch mal ein paar Tage nicht da sind (und absperren). =Lösungsansätze= Kurz den/die entsprechenden LS-Schalter zu werfen ist leider auch keine Option. Das genauere Warum habe ich nicht weiter hinterfragt, das muss man einfach als gegeben annehmen. Dabei ist Strom trennen einfach wie effektiv. Eine Zeitschaltuhr würde helfen, die billigeren haben aber recht grobe Zeitraster und dementsprechend lange Ausfallzeiten. Auch kann es natürlich gleich nach einem Zwangsneustart gleich wieder zu Problemen kommen und die Wartezeit zum nächsten Neustart wird unnötig lang. Zwischenstecker mit Tasmota o. ä. würden zwar das Problem mit der Ausschaltzeit lösen, hätten aber wenig Chancen gegen Problem 2. Zwar könnten diese checken, ob das WLAN wegfällt, die Unterkunft wird allerdings durch mehrere Freifunk-Router (mit gleicher SSID) versorgt. Unnötig viel Komplexität. =Die Idee= Man sieht es den Routern von außen an, wenn sie abschmieren – im Betrieb leuchtet die Power-LED permanent blau, bei einem Crash bzw. Bootloop blinkt sie orange vor sich hin. Mit ein bisschen Mustererkennung erkennt man sogar die Phasen. Warum also nicht einen kleinen Mikrocontroller auf die Status-LED(s) schauen lassen und das "have you tried to turn it off and on again"-Spiel spielen lassen? ==Datensammeln== Am Anfang war die Beobachtung: In einem kleinen WhatsApp-Video bekam ich das unheilvolle orange blinken von einem Vereinsmitglied; ein paar Sekunden sind jedoch noch nicht die ganze Geschichte, deshalb holte ich mir einen der Router nach Hause und nahm ein Video von einem Kaltstart des Gerätes auf und wartete ein bisschen. Ein paar Tage am Netz und siehe da: ohne Zutun von außen blinkt die Power-LED orange. Also nochmal die Kamera raus, Aufnahme und einige Minuten laufen lassen. Als Referenz gab es dann noch ein Video von einem erfolgreichen Start: [ff_rebooter_xiaomi_start.mp4] Mit den Videos kann man sich die Mäusedisco nun wieder und wieder ansehen, Bild für Bild durchgehen und die Blinkzyklen aufschreiben, oder man ist faul und fragt ChatGPT, wie man mit Python die Farben von Pixeln in Videos ermittelt. Ok, das ist wirklich keine rocket science (und einfach nur in der Doku von OpenCV zu stöbern hätte gereicht), aber schon erstaunlich, was Wortstatistik auf Steroiden leisten kann. ==Videoauswertung== Für den ersten Eindruck ist die Herangehensweise eher unakademisch - das Beispiel vom Chatbot wird angepasst, damit an zwei Punkten - Power- und Link-LED - die Farben ermittelt werden, diese werden als Zellenhintergrund für eine HTML-Tabelle ausgegeben. Einfach wie fatal. Um nicht nur einen Pixel zu sampeln, wird jeder Frame um den Faktor 16 dezimiert - statt 1280x720 wird also ein Bild der Größe 80x45 verwendet. Das macht den Prozess nicht schneller, dafür werden Rauschen und Überstrahlungseffekte etwas reduziert. <source lang="python"> import cv2 video = cv2.VideoCapture("S1040005.MP4") frame_decimation = 16 frame_skip = 1 probe_points = [[970, 173], [1039, 168]] framecnt = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) print(framecnt) print("<style> body { background-color: black; } td { width: 20px; height: 1px; } </style>") print("<table style=\"border-collapse: collapse;\">") for frame_number in range(0, framecnt, frame_skip): video.set(1, frame_number) # Read the frame success, frame = video.read() newsize = (int(frame.shape[1] / frame_decimation), int(frame.shape[0] / frame_decimation)) resized = cv2.resize(frame, newsize, interpolation = cv2.INTER_AREA) # Get the color of the pixel at the given location cols = [] for point in probe_points: (b, g, r) = resized[int(point[1]/frame_decimation), int(point[0] / frame_decimation)] cols.append(f"#{r:02X}{g:02X}{b:02X}") #print("\t".join(cols)) print("<tr>" + "".join(map(lambda x : f"<td style=\"background-color: {x}\"> </td>", cols)) + "</tr>") print("</table>") video.release() </source> Bei Videomaterial mit 25 fps (was zugegebenermaßen etwas wenig ist), sieht ein etwas längerer Ausschnitt des Videos oben wie folgt aus: <gallery> ff_rebooter_xiaomi_start.png | Start des Xiaomi-Routers </gallery> Links, wie im Video oben, die Power-LED, rechts die Link-LED. Wie aus dem Quellcode ersichtlich sein sollte, entspricht bei frame_skip = 1 jedes Frame ein Pixel in y-Richtung bei 25 fps. "Misst" man die Pixel vom ersten Lebenszeichen der linken LED bis sie blau wird, "vergehen" 1840 Pixel und somit 73,6 s - nicht ganz. Weil HTML ist das was man eingibt nicht unbedingt das, was angezeigt wird. Laut Konsole ist jeder oben angegebene Pixel 2px in der Darstellung, somit beträgt die Boot-Zeit 36,8 s. Der Bootloop ist nicht spektakulärer, er ist lediglich die immerwährende Wiederholung des "orangen" Parts. =Umsetzung= ==Hardware== Der erste Gedanke war, die Hardware minimalinvasiv aufzubauen: Nachdem es Dauerlicht nur gibt, wenn die Kiste läuft, ist die Farbe irrelevant. Blinkt etwas länger, ist etwas im Argen. Also warum nicht einfach einen Fototransistor anflanschen, die Helligkeit auswerten und wenn längeres Blinken herrscht denk Anker werfen? Es scheitert wie immer an der Realität. Die ersten Versuche waren aussichtsreich, mit Umgebungslicht und nicht exakt platziertem Fototransistor war die Freude aber recht schnell wieder vorbei. Für die ersten Versuche auf dem Breadboard hat es zumindest gereicht. Um nicht extra Teile bestellen zu müssen, wurde das eingeplant, was herum liegt, Herzstück ist ein (völlig überdimensionierter) ATmega8A, der Signale zweier Fototransistoren im SMD-Package, aber auch in der THT-Version in Form von BPW40 entgegennimmt. Um beide LEDs am Router erfassen zu können, sind diese im Abstand von 15 mm zueinander platziert. Auf der anderen Seite des Mikrocontrollers hängen p-Kanal FETs sowohl im SO-8- als auch SOT-23-Gehäuse, über die die Versorgung des Routers geschaltet wird. Um evtl. doch noch einen UART mit abweichender Spannung (und Domäne) anbinden zu können, noch zwei einfache Levelshifter dazu und ab auf eine Leiterkarte damit. Noch zwei Status-LEDs dazu und fertig ist der Lack. Recht viel Optionales, aber eine zweiten Leiterkarten-Spin zu fahren: #gerkeinbock Leiterkarten-Spin? Ja, mittlerweile bin ich echt zu faul, etwas auf Lochraster aufzubauen - zumal so gut wie alle Bauteile im SMD-Package daherkommen. Der zusammengeklöppelte Schaltplan, Layout und der Aufbau sehen wie folgt aus: <gallery> ff_rebooter_sch.png | Schaltplan ff_rebooter_pcb.png | Layout der Leiterkarte ff_rebooter_pcb_top.jpg | Bestückte Oberseite ff_rebooter_pcb_bot.jpg | Bestückte Unterseite </gallery> ===BOM & Nachbau=== Nachdem die Hardware schnell-schnell zusammengeklöppelt wurde, ist aktuell keine BOM und genauere Details vorgesehen. Wer sie dennoch möchte, kann sie gerne aus den EAGLE-Daten erzeugen oder mich anschreiben. ==Firmware== Die Software hat im Prinzip nur eine Aufgabe: Blinkt die Power LED länger als x Sekunden, wird die Stromversorgung für y Sekunden unterbrochen. "Genau das, nur etwas komplizierter!" Zunächst gilt die Frage zu klären: Wann blinkt was, wann ist es statisch an, wann aus? ===ADC=== Vorher muss aber erst noch geklärt werden: Wann ist eine LED überhaupt an? Mit den vorhin erwähnten Fototransistoren muss man das Umgebungslicht filtern. Ist die LED länger statisch und das Licht "außenrum" ändert sich, oder es verrutscht etwas leicht, verpasst man vielleicht, dass sich etwas ändert. Kann man filtern, kann man aber auch von Grund auf vermeiden. auch wenn die Elektronik dafür vorgesehen ist: man muss die optischen Sensoren nicht verwenden, sondern kann auch einfach auf die Ansteuerung der LEDs gehen. Diese erfolgt jedoch nicht mit boardähnlichen 5 V, sondern mit 3,3 V, was für die Eingänge etwas knapp werden kann. Also kommt doch der ADC zum Einsatz, wenn auch etwas vereinfacht: zwei Schwellenwerte, dazwischen eine Hysterese, fertig. Einen Schritt zurück: Der Analog zu Digital-Wandler durchläuft, nachdem das "Subsystem" getriggert wurde alle ausgewählten Kanäle, was etwa jede Millisekunde geschieht. Schwellenwertvergleich und ab mit einem true oder false in die LED-Detektion. ===LED-Detektion=== Diese schaut, ob sich was am Zustand des Einganges ändert und zählt die entsprechende Zeit. Wechselt der Zustand nach "0" (false) wird erst einmal blinkend angenommen, bleibt der Zustand für länger als <code>LEDDET_TIMEOUT</code> (750 ms) konstant, wird "statisch aus" respektive "an" angenommen. Das Ganze wird für die rote und blaue LED der "Power-LED" gemacht... ===Zustandsautomat=== ... und im "Target"-Zustandsautomaten verwurstet, der zunächst auf Papier entstand und nach der Implementierung auf dem PC nachgezeichnet wurde: <gallery> ff_rebooter_fsm.png | Zustandsautomat für das "Target" </gallery> Nach dem Einschalten geht die Maschine zunächst in den Off-Zustand - hauptsächlich um die Realität abzubilden. Beim Startup wird die Stromversorgung für den Router eingeschaltet und die grüne LED blinkt vor sich hin. Sobald für länger als 2 Sekunden die orange LED des Routers erloschen ist und die blaue leuchtet, wird angenommen dass der Router läuft. Ist das nach 90 Sekunden am Strom nicht der Fall, wird ein Crash angenommen und ein harter Reboot eingeleitet (mehr dazu später). Im Zustand Running gibt es zwei Varianten für die eigenen Status-LEDs: In jedem Fall leuchtet die grüne LED dauerhaft, wurde vorher ein Crash "erkannt", blitzt zusätzlich die rote LED auf. Sollte nun am Router die orange LED an gehen oder blinken und die die blaue LED nicht an sein, gibt es einen Crashverdacht; allerdings erst, wenn dies für über 2 Sekunden mit "Waterlevel" der Fall ist. Mit Waterlevel ist gemeint, dass im "Verdachtszustand" ein Zähler hochgezählt wird. Ist der "Verdacht" vorbei, wird dieser Zähler nicht auf Null zurückgesetzt, sondern lediglich verringert. So kann ein instabiler Zustand etwas besser erkannt werden. Erhärtet sich der Crashverdacht, wird ein interner Zähler für die Verdachtsfälle hochgezählt, erreicht dieser die magische Anzahl 3 oder bleibt der Zustand für über 90 Sekunden, wird ein Neustart eingeleitet. "Fängt" sich der Router wieder, sprich: die blaue LED leuchtet konstant und die orange ist aus, wechselt der Zustand nach 5 Sekunden wieder nach Running. Allerdings hier ohne Waterlevel. Lieber einen harten Neustart als im Limbus zwischen Running und Crashed hängen bleiben. Da beim erhärteten Crashverdacht vermutlich nix mehr geht, darf nun die rote Status-LED blinken, die grüne bleibt dunkel. Beim Durchführen des Reboots wird die Stromversorgung zum Router unterbrochen und die rote Status-LED blinkt schnell. Nach 5 Sekunden beginnt der Lebenszyklus des Routers von Vorne (Off) und er darf wieder starten. Wozu der Aufwand? Der Router startet zwar recht schnell (etwa 40 Sekunden reine Bootzeit), benötigt im dümmsten Fall aber 1-2 Minuten, bis er wieder mit dem Freifunk-Netz verbunden ist. Daher sollen unnötige Reboots vermieden werden. Warum aber so lange Wartezeiten, bevor der Strom abgedreht wird? Auch hier: Vorsicht. Es gibt auch legitime Gründe, warum der Router einen "Crash" hinlegt. Dieser lässt sich nicht von einem (gewollten) Neustart unterscheiden, sei es ein Admin aus der Ferne oder ein Firmware-Update. Gerade letzteres sollte man nicht durch einen harten Neustart unterbrechen. Nach einem Test dauert der erste Start nach einem Update unter 90 Sekunden, mal hoffen, dass sich das auch so im Feld verhält - schließlich sitzen die Bewohner nicht gerne ohne Internet und ich stehe ungern vor verschlossenen Türen, wenn es etwas zu tun gibt. Damit nicht der Mikrocontroller zum Problemfall wird, ist der interne Watchdog permanent aktiviert und wird (mehr oder weniger sinnvoll) im Mainloop zurückgesetzt. ==Einbau== Dafür, dass nach erstem Plan ein 3D-Druck-Gehäuse auf den Router geklebt werden sollte, hat sich ein fast idealer Platz im Gehäuse selbst gefunden - und auch für die Integration hatte Xiaomi ein Herz für Bastler. Oder zumindest beschlossen, dass ein 0-Ohm-Widerstand (R752) als Sicherung reicht. Mit dem nicht genutzten Verpolschutz (D12) gibt es auch ein Massepad direkt nebenan: <gallery> ff_rebooter_xiaomi_input.jpg | Eingangsbeschaltung am Router </gallery> An dieser Stelle sei angemerkt, dass man sicherlich auch den Enable/Shutdown-Pin des/der Regler hätte verwenden können, bei der unbekannten Beschaltung und den Widerständen im 0201-Gehäuse wawr es mir allerdings zu fummelig, dort einzugreifen. Den LEDs sieht man es mit scharfem Auge schon an, welche die orange und welche die blaue sein muss (wenn auch nicht unbedingt im Foto): Blaue LEDs haben (wie weiße) üblicherweise 2 Bond-Drähte, der ideale Abgriffpunkt ist zwischen Vorwiderstand und Kondensator: <gallery> ff_rebooter_router_leds.jpg | Status-LEDs am Router ff_rebooter_router_leds_detail.jpg | Detail-Ansicht der Dual-LED ff_rebooter_router_leds_beschaltung.jpg | Abgriffpunkte für die LEDs </gallery> Auf- und Eingebaut sieht es dann wie folgt aus: <gallery> ff_rebooter_xiaomi_einbau.jpg | Einbau des Rebooters im Router </gallery> Im Foto fehlt noch der obligatorische Heißkleber. Der Kondensator des Implantates musste noch ein bisschen gebogen werden, damit er nicht mit dem Gehäusedeckel kollidiert. Die abgeschnittenen Drähte sind ein Überbleibsel der oben erwähnten Logging-Aktivitäten (und wurden noch gestutzt). Die verbaute supergrüne LED ist trotz niedrigem Strom recht hell - sie ist, obwohl nach unten gerichtet, durch das Gehäuse leicht sichtbar und projiziert einen deutlichen Lichtkeil unter den gelöcherten Gehäuseboden. Kann man auch als Feature betrachten. =Das Ergebnis= Die ersten Tests mit per Konsole abgesetzten Reboots und einem erzwungenen Update waren erfolgreich - bei der Gelegenheit wurde auch gleich die Debug-Ausgaben eines Lebenszyklus (leider ohne Timestamps) aufgezeichnet: <pre> Built on: Apr 2 2023 21:47:12 Target: off -> off Target: off -> startup LED or: blinking LED bl: blinking LED bl: off LED or: on LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: startup finished Target: startup -> running Target: running, saw 0 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: recovered from crash state, saw 1 crashes Target: crashed -> running Target: running, saw 1 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: recovered from crash state, saw 2 crashes Target: crashed -> running Target: running, saw 2 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed Target: saw 3 crashes, reboot Target: crashed -> reboot LED bl: on Target: reboot -> off Target: off -> startup LED or: blinking LED bl: blinking LED bl: off LED or: on LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: startup finished Target: startup -> running Target: running, saw 0 crashes </pre> Patient 1 ist zum Zeitpunkt der Erstellung dieses Artikels seit 7 Tagen im Einsatz, legte erst einmal einen Lauf von knapp 5 Tagen hin und brauchte dann in etwa in etwa alle 12-17 Stunden einen Tritt. Router 2 ist erst seit kurzer Zeit wieder am Netz und hat kurz nach dem Start mutmaßlich einen Crash auf dem anderen Router verursacht - zumindest gab es eine verdächtige Korrelation zwischen Einschalten von Router 2 und einem Crash von Router 1. Bei beiden Geräten wurden die Cronjobs für den nächtlichen Reboot deaktiviert. Andere Faktoren die Abstürze begünstigen sind mir aktuell nicht bekannt - bei beiden Geräten habe ich vor der Wiederinbetriebnahme ein Update erzwungen, bei einem auch manuell Caches geleert. Vielleicht bringt das was, vielleicht auch nicht. Auch gilt es noch WLAN-Mesh auf zumindest einem der Geräte zu deaktivieren, zumal beide über Kabel angebunden sind und Komplexität sicherlich nicht zur Stabilität beitragen. =Ausblick= Die Schaltung kann verkleinert und optimiert werden, alles Unnötige entfernt werden. Hintergedanke für den Levelshifter an der UART-Schnittstelle war, über die Menge an Ausgaben (oder Keywords) einen Absturz zu erkennen oder auch Rückmeldungen z. B. per HTTP-Request auf die Konsole zu injizieren. Geschadet hat das Vorsehen sicher nicht, dank der bisherigen Zuverlässigkeit der aktuellen Erkennungsmethode und Statistik-Tools von ffmuc ist das aber nicht nötig. Wenn die Geräte etwas länger wieder im Betrieb sind, wird es ein Update geben. Generell halte ich einen externen Watchdog für Geräte, auf die man keinen permanenten Zugriff hat, für essenziell. Besser wäre natürlich, wenn es gar nicht bräuchte - was ich nicht als Kritik an [https://ffmuc.net/ Freifunk München]/[https://github.com/freifunk-gluon/gluon Gluon]/[https://openwrt.org/ OpenWRT] meine. Die Projekte leben überwiegend von freiwilligen, die in ihrer Freizeit und Community mehr bewegen als manch kommerzielle Anbieter. =Downloads= * [[ff_rebooter_v0.1.zip]] Schaltplan & Layout im EAGLE-Format und Firmware als Microchip-Studio-Projekt [[Kategorie:AVR]] [[Kategorie:Netzwerk]] 403b44a09baa401e1798a0d472e1a9576397c4e4 1854 1853 2023-04-11T20:16:15Z Chris 2 /* Datensammeln */ wikitext text/x-wiki =Ausgangssituation= In unseren Flüchtlingsunterkünften stehen mehrere Xiaomi Mi Router 4A Gigabit Edition, die mit der Freifunk-München-Firmware bespielt sind. Wer Freifunk nicht kennt, kann und sollte am besten sich in der [[wpde:Freifunk|Wikipedia]] informieren. Was am Anfang noch recht gut funktionierte, wurde mit der Zeit immer instabiler. Ein Cronjob zum nächtlichen Neustart brachte zwar Besserung, aber nach ein paar Tagen gingen die Router in eine Bootloop. Um den Fehler besser zu verstehen, wurde zeitweise ein [https://hobbyelektronik.org/b/2022/10/uart-logging-mit-linux/ Raspberry Pi zum Protokollieren] abgestellt. Als jemand, der von Linux nur rudimentäres Wissen besitzt, sahen die Meldungen so aus, als könne der SoC einen der WLAN-Chips nicht mehr initialisieren und schoss sich ins Nirwana. Blöd: ein Reboot richtet das nicht, Dokumentation für die Chips hängt wohl hinter der NDA-Mauer und einen hard-reset scheint es nicht zu geben. Nach einem kurzen Austausch im Chat der Freifunker gab es ein Ticket bei OpenWRT und nach einigen paar Tagen auch eine Experimental-Firmware, die den Fehler beheben sollte. Sollte. Ein paar Tage später stand bei Grafana für die Knoten wieder "no data", dafür gab es Klagen aus der Unterkunft. Einer der Router steht hinter für die dauerhaft verschlossener Tür, der andere in einem Zimmer dessen Bewohner auch mal ein paar Tage nicht da sind (und absperren). =Lösungsansätze= Kurz den/die entsprechenden LS-Schalter zu werfen ist leider auch keine Option. Das genauere Warum habe ich nicht weiter hinterfragt, das muss man einfach als gegeben annehmen. Dabei ist Strom trennen einfach wie effektiv. Eine Zeitschaltuhr würde helfen, die billigeren haben aber recht grobe Zeitraster und dementsprechend lange Ausfallzeiten. Auch kann es natürlich gleich nach einem Zwangsneustart gleich wieder zu Problemen kommen und die Wartezeit zum nächsten Neustart wird unnötig lang. Zwischenstecker mit Tasmota o. ä. würden zwar das Problem mit der Ausschaltzeit lösen, hätten aber wenig Chancen gegen Problem 2. Zwar könnten diese checken, ob das WLAN wegfällt, die Unterkunft wird allerdings durch mehrere Freifunk-Router (mit gleicher SSID) versorgt. Unnötig viel Komplexität. =Die Idee= Man sieht es den Routern von außen an, wenn sie abschmieren – im Betrieb leuchtet die Power-LED permanent blau, bei einem Crash bzw. Bootloop blinkt sie orange vor sich hin. Mit ein bisschen Mustererkennung erkennt man sogar die Phasen. Warum also nicht einen kleinen Mikrocontroller auf die Status-LED(s) schauen lassen und das "have you tried to turn it off and on again"-Spiel spielen lassen? ==Datensammeln== Am Anfang war die Beobachtung: In einem kleinen WhatsApp-Video bekam ich das unheilvolle orange blinken von einem Vereinsmitglied; ein paar Sekunden sind jedoch noch nicht die ganze Geschichte, deshalb holte ich mir einen der Router nach Hause und nahm ein Video von einem Kaltstart des Gerätes auf und wartete ein bisschen. Ein paar Tage am Netz und siehe da: ohne Zutun von außen blinkt die Power-LED orange. Also nochmal die Kamera raus, Aufnahme und einige Minuten laufen lassen. Als Referenz gab es dann noch ein Video von einem erfolgreichen Start: [Datei:ff_rebooter_xiaomi_start.mp4] Mit den Videos kann man sich die Mäusedisco nun wieder und wieder ansehen, Bild für Bild durchgehen und die Blinkzyklen aufschreiben, oder man ist faul und fragt ChatGPT, wie man mit Python die Farben von Pixeln in Videos ermittelt. Ok, das ist wirklich keine rocket science (und einfach nur in der Doku von OpenCV zu stöbern hätte gereicht), aber schon erstaunlich, was Wortstatistik auf Steroiden leisten kann. ==Videoauswertung== Für den ersten Eindruck ist die Herangehensweise eher unakademisch - das Beispiel vom Chatbot wird angepasst, damit an zwei Punkten - Power- und Link-LED - die Farben ermittelt werden, diese werden als Zellenhintergrund für eine HTML-Tabelle ausgegeben. Einfach wie fatal. Um nicht nur einen Pixel zu sampeln, wird jeder Frame um den Faktor 16 dezimiert - statt 1280x720 wird also ein Bild der Größe 80x45 verwendet. Das macht den Prozess nicht schneller, dafür werden Rauschen und Überstrahlungseffekte etwas reduziert. <source lang="python"> import cv2 video = cv2.VideoCapture("S1040005.MP4") frame_decimation = 16 frame_skip = 1 probe_points = [[970, 173], [1039, 168]] framecnt = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) print(framecnt) print("<style> body { background-color: black; } td { width: 20px; height: 1px; } </style>") print("<table style=\"border-collapse: collapse;\">") for frame_number in range(0, framecnt, frame_skip): video.set(1, frame_number) # Read the frame success, frame = video.read() newsize = (int(frame.shape[1] / frame_decimation), int(frame.shape[0] / frame_decimation)) resized = cv2.resize(frame, newsize, interpolation = cv2.INTER_AREA) # Get the color of the pixel at the given location cols = [] for point in probe_points: (b, g, r) = resized[int(point[1]/frame_decimation), int(point[0] / frame_decimation)] cols.append(f"#{r:02X}{g:02X}{b:02X}") #print("\t".join(cols)) print("<tr>" + "".join(map(lambda x : f"<td style=\"background-color: {x}\"> </td>", cols)) + "</tr>") print("</table>") video.release() </source> Bei Videomaterial mit 25 fps (was zugegebenermaßen etwas wenig ist), sieht ein etwas längerer Ausschnitt des Videos oben wie folgt aus: <gallery> ff_rebooter_xiaomi_start.png | Start des Xiaomi-Routers </gallery> Links, wie im Video oben, die Power-LED, rechts die Link-LED. Wie aus dem Quellcode ersichtlich sein sollte, entspricht bei frame_skip = 1 jedes Frame ein Pixel in y-Richtung bei 25 fps. "Misst" man die Pixel vom ersten Lebenszeichen der linken LED bis sie blau wird, "vergehen" 1840 Pixel und somit 73,6 s - nicht ganz. Weil HTML ist das was man eingibt nicht unbedingt das, was angezeigt wird. Laut Konsole ist jeder oben angegebene Pixel 2px in der Darstellung, somit beträgt die Boot-Zeit 36,8 s. Der Bootloop ist nicht spektakulärer, er ist lediglich die immerwährende Wiederholung des "orangen" Parts. =Umsetzung= ==Hardware== Der erste Gedanke war, die Hardware minimalinvasiv aufzubauen: Nachdem es Dauerlicht nur gibt, wenn die Kiste läuft, ist die Farbe irrelevant. Blinkt etwas länger, ist etwas im Argen. Also warum nicht einfach einen Fototransistor anflanschen, die Helligkeit auswerten und wenn längeres Blinken herrscht denk Anker werfen? Es scheitert wie immer an der Realität. Die ersten Versuche waren aussichtsreich, mit Umgebungslicht und nicht exakt platziertem Fototransistor war die Freude aber recht schnell wieder vorbei. Für die ersten Versuche auf dem Breadboard hat es zumindest gereicht. Um nicht extra Teile bestellen zu müssen, wurde das eingeplant, was herum liegt, Herzstück ist ein (völlig überdimensionierter) ATmega8A, der Signale zweier Fototransistoren im SMD-Package, aber auch in der THT-Version in Form von BPW40 entgegennimmt. Um beide LEDs am Router erfassen zu können, sind diese im Abstand von 15 mm zueinander platziert. Auf der anderen Seite des Mikrocontrollers hängen p-Kanal FETs sowohl im SO-8- als auch SOT-23-Gehäuse, über die die Versorgung des Routers geschaltet wird. Um evtl. doch noch einen UART mit abweichender Spannung (und Domäne) anbinden zu können, noch zwei einfache Levelshifter dazu und ab auf eine Leiterkarte damit. Noch zwei Status-LEDs dazu und fertig ist der Lack. Recht viel Optionales, aber eine zweiten Leiterkarten-Spin zu fahren: #gerkeinbock Leiterkarten-Spin? Ja, mittlerweile bin ich echt zu faul, etwas auf Lochraster aufzubauen - zumal so gut wie alle Bauteile im SMD-Package daherkommen. Der zusammengeklöppelte Schaltplan, Layout und der Aufbau sehen wie folgt aus: <gallery> ff_rebooter_sch.png | Schaltplan ff_rebooter_pcb.png | Layout der Leiterkarte ff_rebooter_pcb_top.jpg | Bestückte Oberseite ff_rebooter_pcb_bot.jpg | Bestückte Unterseite </gallery> ===BOM & Nachbau=== Nachdem die Hardware schnell-schnell zusammengeklöppelt wurde, ist aktuell keine BOM und genauere Details vorgesehen. Wer sie dennoch möchte, kann sie gerne aus den EAGLE-Daten erzeugen oder mich anschreiben. ==Firmware== Die Software hat im Prinzip nur eine Aufgabe: Blinkt die Power LED länger als x Sekunden, wird die Stromversorgung für y Sekunden unterbrochen. "Genau das, nur etwas komplizierter!" Zunächst gilt die Frage zu klären: Wann blinkt was, wann ist es statisch an, wann aus? ===ADC=== Vorher muss aber erst noch geklärt werden: Wann ist eine LED überhaupt an? Mit den vorhin erwähnten Fototransistoren muss man das Umgebungslicht filtern. Ist die LED länger statisch und das Licht "außenrum" ändert sich, oder es verrutscht etwas leicht, verpasst man vielleicht, dass sich etwas ändert. Kann man filtern, kann man aber auch von Grund auf vermeiden. auch wenn die Elektronik dafür vorgesehen ist: man muss die optischen Sensoren nicht verwenden, sondern kann auch einfach auf die Ansteuerung der LEDs gehen. Diese erfolgt jedoch nicht mit boardähnlichen 5 V, sondern mit 3,3 V, was für die Eingänge etwas knapp werden kann. Also kommt doch der ADC zum Einsatz, wenn auch etwas vereinfacht: zwei Schwellenwerte, dazwischen eine Hysterese, fertig. Einen Schritt zurück: Der Analog zu Digital-Wandler durchläuft, nachdem das "Subsystem" getriggert wurde alle ausgewählten Kanäle, was etwa jede Millisekunde geschieht. Schwellenwertvergleich und ab mit einem true oder false in die LED-Detektion. ===LED-Detektion=== Diese schaut, ob sich was am Zustand des Einganges ändert und zählt die entsprechende Zeit. Wechselt der Zustand nach "0" (false) wird erst einmal blinkend angenommen, bleibt der Zustand für länger als <code>LEDDET_TIMEOUT</code> (750 ms) konstant, wird "statisch aus" respektive "an" angenommen. Das Ganze wird für die rote und blaue LED der "Power-LED" gemacht... ===Zustandsautomat=== ... und im "Target"-Zustandsautomaten verwurstet, der zunächst auf Papier entstand und nach der Implementierung auf dem PC nachgezeichnet wurde: <gallery> ff_rebooter_fsm.png | Zustandsautomat für das "Target" </gallery> Nach dem Einschalten geht die Maschine zunächst in den Off-Zustand - hauptsächlich um die Realität abzubilden. Beim Startup wird die Stromversorgung für den Router eingeschaltet und die grüne LED blinkt vor sich hin. Sobald für länger als 2 Sekunden die orange LED des Routers erloschen ist und die blaue leuchtet, wird angenommen dass der Router läuft. Ist das nach 90 Sekunden am Strom nicht der Fall, wird ein Crash angenommen und ein harter Reboot eingeleitet (mehr dazu später). Im Zustand Running gibt es zwei Varianten für die eigenen Status-LEDs: In jedem Fall leuchtet die grüne LED dauerhaft, wurde vorher ein Crash "erkannt", blitzt zusätzlich die rote LED auf. Sollte nun am Router die orange LED an gehen oder blinken und die die blaue LED nicht an sein, gibt es einen Crashverdacht; allerdings erst, wenn dies für über 2 Sekunden mit "Waterlevel" der Fall ist. Mit Waterlevel ist gemeint, dass im "Verdachtszustand" ein Zähler hochgezählt wird. Ist der "Verdacht" vorbei, wird dieser Zähler nicht auf Null zurückgesetzt, sondern lediglich verringert. So kann ein instabiler Zustand etwas besser erkannt werden. Erhärtet sich der Crashverdacht, wird ein interner Zähler für die Verdachtsfälle hochgezählt, erreicht dieser die magische Anzahl 3 oder bleibt der Zustand für über 90 Sekunden, wird ein Neustart eingeleitet. "Fängt" sich der Router wieder, sprich: die blaue LED leuchtet konstant und die orange ist aus, wechselt der Zustand nach 5 Sekunden wieder nach Running. Allerdings hier ohne Waterlevel. Lieber einen harten Neustart als im Limbus zwischen Running und Crashed hängen bleiben. Da beim erhärteten Crashverdacht vermutlich nix mehr geht, darf nun die rote Status-LED blinken, die grüne bleibt dunkel. Beim Durchführen des Reboots wird die Stromversorgung zum Router unterbrochen und die rote Status-LED blinkt schnell. Nach 5 Sekunden beginnt der Lebenszyklus des Routers von Vorne (Off) und er darf wieder starten. Wozu der Aufwand? Der Router startet zwar recht schnell (etwa 40 Sekunden reine Bootzeit), benötigt im dümmsten Fall aber 1-2 Minuten, bis er wieder mit dem Freifunk-Netz verbunden ist. Daher sollen unnötige Reboots vermieden werden. Warum aber so lange Wartezeiten, bevor der Strom abgedreht wird? Auch hier: Vorsicht. Es gibt auch legitime Gründe, warum der Router einen "Crash" hinlegt. Dieser lässt sich nicht von einem (gewollten) Neustart unterscheiden, sei es ein Admin aus der Ferne oder ein Firmware-Update. Gerade letzteres sollte man nicht durch einen harten Neustart unterbrechen. Nach einem Test dauert der erste Start nach einem Update unter 90 Sekunden, mal hoffen, dass sich das auch so im Feld verhält - schließlich sitzen die Bewohner nicht gerne ohne Internet und ich stehe ungern vor verschlossenen Türen, wenn es etwas zu tun gibt. Damit nicht der Mikrocontroller zum Problemfall wird, ist der interne Watchdog permanent aktiviert und wird (mehr oder weniger sinnvoll) im Mainloop zurückgesetzt. ==Einbau== Dafür, dass nach erstem Plan ein 3D-Druck-Gehäuse auf den Router geklebt werden sollte, hat sich ein fast idealer Platz im Gehäuse selbst gefunden - und auch für die Integration hatte Xiaomi ein Herz für Bastler. Oder zumindest beschlossen, dass ein 0-Ohm-Widerstand (R752) als Sicherung reicht. Mit dem nicht genutzten Verpolschutz (D12) gibt es auch ein Massepad direkt nebenan: <gallery> ff_rebooter_xiaomi_input.jpg | Eingangsbeschaltung am Router </gallery> An dieser Stelle sei angemerkt, dass man sicherlich auch den Enable/Shutdown-Pin des/der Regler hätte verwenden können, bei der unbekannten Beschaltung und den Widerständen im 0201-Gehäuse wawr es mir allerdings zu fummelig, dort einzugreifen. Den LEDs sieht man es mit scharfem Auge schon an, welche die orange und welche die blaue sein muss (wenn auch nicht unbedingt im Foto): Blaue LEDs haben (wie weiße) üblicherweise 2 Bond-Drähte, der ideale Abgriffpunkt ist zwischen Vorwiderstand und Kondensator: <gallery> ff_rebooter_router_leds.jpg | Status-LEDs am Router ff_rebooter_router_leds_detail.jpg | Detail-Ansicht der Dual-LED ff_rebooter_router_leds_beschaltung.jpg | Abgriffpunkte für die LEDs </gallery> Auf- und Eingebaut sieht es dann wie folgt aus: <gallery> ff_rebooter_xiaomi_einbau.jpg | Einbau des Rebooters im Router </gallery> Im Foto fehlt noch der obligatorische Heißkleber. Der Kondensator des Implantates musste noch ein bisschen gebogen werden, damit er nicht mit dem Gehäusedeckel kollidiert. Die abgeschnittenen Drähte sind ein Überbleibsel der oben erwähnten Logging-Aktivitäten (und wurden noch gestutzt). Die verbaute supergrüne LED ist trotz niedrigem Strom recht hell - sie ist, obwohl nach unten gerichtet, durch das Gehäuse leicht sichtbar und projiziert einen deutlichen Lichtkeil unter den gelöcherten Gehäuseboden. Kann man auch als Feature betrachten. =Das Ergebnis= Die ersten Tests mit per Konsole abgesetzten Reboots und einem erzwungenen Update waren erfolgreich - bei der Gelegenheit wurde auch gleich die Debug-Ausgaben eines Lebenszyklus (leider ohne Timestamps) aufgezeichnet: <pre> Built on: Apr 2 2023 21:47:12 Target: off -> off Target: off -> startup LED or: blinking LED bl: blinking LED bl: off LED or: on LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: startup finished Target: startup -> running Target: running, saw 0 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: recovered from crash state, saw 1 crashes Target: crashed -> running Target: running, saw 1 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: recovered from crash state, saw 2 crashes Target: crashed -> running Target: running, saw 2 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed Target: saw 3 crashes, reboot Target: crashed -> reboot LED bl: on Target: reboot -> off Target: off -> startup LED or: blinking LED bl: blinking LED bl: off LED or: on LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: startup finished Target: startup -> running Target: running, saw 0 crashes </pre> Patient 1 ist zum Zeitpunkt der Erstellung dieses Artikels seit 7 Tagen im Einsatz, legte erst einmal einen Lauf von knapp 5 Tagen hin und brauchte dann in etwa in etwa alle 12-17 Stunden einen Tritt. Router 2 ist erst seit kurzer Zeit wieder am Netz und hat kurz nach dem Start mutmaßlich einen Crash auf dem anderen Router verursacht - zumindest gab es eine verdächtige Korrelation zwischen Einschalten von Router 2 und einem Crash von Router 1. Bei beiden Geräten wurden die Cronjobs für den nächtlichen Reboot deaktiviert. Andere Faktoren die Abstürze begünstigen sind mir aktuell nicht bekannt - bei beiden Geräten habe ich vor der Wiederinbetriebnahme ein Update erzwungen, bei einem auch manuell Caches geleert. Vielleicht bringt das was, vielleicht auch nicht. Auch gilt es noch WLAN-Mesh auf zumindest einem der Geräte zu deaktivieren, zumal beide über Kabel angebunden sind und Komplexität sicherlich nicht zur Stabilität beitragen. =Ausblick= Die Schaltung kann verkleinert und optimiert werden, alles Unnötige entfernt werden. Hintergedanke für den Levelshifter an der UART-Schnittstelle war, über die Menge an Ausgaben (oder Keywords) einen Absturz zu erkennen oder auch Rückmeldungen z. B. per HTTP-Request auf die Konsole zu injizieren. Geschadet hat das Vorsehen sicher nicht, dank der bisherigen Zuverlässigkeit der aktuellen Erkennungsmethode und Statistik-Tools von ffmuc ist das aber nicht nötig. Wenn die Geräte etwas länger wieder im Betrieb sind, wird es ein Update geben. Generell halte ich einen externen Watchdog für Geräte, auf die man keinen permanenten Zugriff hat, für essenziell. Besser wäre natürlich, wenn es gar nicht bräuchte - was ich nicht als Kritik an [https://ffmuc.net/ Freifunk München]/[https://github.com/freifunk-gluon/gluon Gluon]/[https://openwrt.org/ OpenWRT] meine. Die Projekte leben überwiegend von freiwilligen, die in ihrer Freizeit und Community mehr bewegen als manch kommerzielle Anbieter. =Downloads= * [[ff_rebooter_v0.1.zip]] Schaltplan & Layout im EAGLE-Format und Firmware als Microchip-Studio-Projekt [[Kategorie:AVR]] [[Kategorie:Netzwerk]] 3a02d9767a7c6a446281f3c182202c8884211d48 1855 1854 2023-04-11T20:17:39Z Chris 2 /* Datensammeln */ das mit dem Video einbetten üben wir nochmal... wikitext text/x-wiki =Ausgangssituation= In unseren Flüchtlingsunterkünften stehen mehrere Xiaomi Mi Router 4A Gigabit Edition, die mit der Freifunk-München-Firmware bespielt sind. Wer Freifunk nicht kennt, kann und sollte am besten sich in der [[wpde:Freifunk|Wikipedia]] informieren. Was am Anfang noch recht gut funktionierte, wurde mit der Zeit immer instabiler. Ein Cronjob zum nächtlichen Neustart brachte zwar Besserung, aber nach ein paar Tagen gingen die Router in eine Bootloop. Um den Fehler besser zu verstehen, wurde zeitweise ein [https://hobbyelektronik.org/b/2022/10/uart-logging-mit-linux/ Raspberry Pi zum Protokollieren] abgestellt. Als jemand, der von Linux nur rudimentäres Wissen besitzt, sahen die Meldungen so aus, als könne der SoC einen der WLAN-Chips nicht mehr initialisieren und schoss sich ins Nirwana. Blöd: ein Reboot richtet das nicht, Dokumentation für die Chips hängt wohl hinter der NDA-Mauer und einen hard-reset scheint es nicht zu geben. Nach einem kurzen Austausch im Chat der Freifunker gab es ein Ticket bei OpenWRT und nach einigen paar Tagen auch eine Experimental-Firmware, die den Fehler beheben sollte. Sollte. Ein paar Tage später stand bei Grafana für die Knoten wieder "no data", dafür gab es Klagen aus der Unterkunft. Einer der Router steht hinter für die dauerhaft verschlossener Tür, der andere in einem Zimmer dessen Bewohner auch mal ein paar Tage nicht da sind (und absperren). =Lösungsansätze= Kurz den/die entsprechenden LS-Schalter zu werfen ist leider auch keine Option. Das genauere Warum habe ich nicht weiter hinterfragt, das muss man einfach als gegeben annehmen. Dabei ist Strom trennen einfach wie effektiv. Eine Zeitschaltuhr würde helfen, die billigeren haben aber recht grobe Zeitraster und dementsprechend lange Ausfallzeiten. Auch kann es natürlich gleich nach einem Zwangsneustart gleich wieder zu Problemen kommen und die Wartezeit zum nächsten Neustart wird unnötig lang. Zwischenstecker mit Tasmota o. ä. würden zwar das Problem mit der Ausschaltzeit lösen, hätten aber wenig Chancen gegen Problem 2. Zwar könnten diese checken, ob das WLAN wegfällt, die Unterkunft wird allerdings durch mehrere Freifunk-Router (mit gleicher SSID) versorgt. Unnötig viel Komplexität. =Die Idee= Man sieht es den Routern von außen an, wenn sie abschmieren – im Betrieb leuchtet die Power-LED permanent blau, bei einem Crash bzw. Bootloop blinkt sie orange vor sich hin. Mit ein bisschen Mustererkennung erkennt man sogar die Phasen. Warum also nicht einen kleinen Mikrocontroller auf die Status-LED(s) schauen lassen und das "have you tried to turn it off and on again"-Spiel spielen lassen? ==Datensammeln== Am Anfang war die Beobachtung: In einem kleinen WhatsApp-Video bekam ich das unheilvolle orange blinken von einem Vereinsmitglied; ein paar Sekunden sind jedoch noch nicht die ganze Geschichte, deshalb holte ich mir einen der Router nach Hause und nahm ein Video von einem Kaltstart des Gerätes auf und wartete ein bisschen. Ein paar Tage am Netz und siehe da: ohne Zutun von außen blinkt die Power-LED orange. Also nochmal die Kamera raus, Aufnahme und einige Minuten laufen lassen. Als Referenz gab es dann noch ein Video von einem erfolgreichen Start: [[Datei:ff_rebooter_xiaomi_start.mp4]] Mit den Videos kann man sich die Mäusedisco nun wieder und wieder ansehen, Bild für Bild durchgehen und die Blinkzyklen aufschreiben, oder man ist faul und fragt ChatGPT, wie man mit Python die Farben von Pixeln in Videos ermittelt. Ok, das ist wirklich keine rocket science (und einfach nur in der Doku von OpenCV zu stöbern hätte gereicht), aber schon erstaunlich, was Wortstatistik auf Steroiden leisten kann. ==Videoauswertung== Für den ersten Eindruck ist die Herangehensweise eher unakademisch - das Beispiel vom Chatbot wird angepasst, damit an zwei Punkten - Power- und Link-LED - die Farben ermittelt werden, diese werden als Zellenhintergrund für eine HTML-Tabelle ausgegeben. Einfach wie fatal. Um nicht nur einen Pixel zu sampeln, wird jeder Frame um den Faktor 16 dezimiert - statt 1280x720 wird also ein Bild der Größe 80x45 verwendet. Das macht den Prozess nicht schneller, dafür werden Rauschen und Überstrahlungseffekte etwas reduziert. <source lang="python"> import cv2 video = cv2.VideoCapture("S1040005.MP4") frame_decimation = 16 frame_skip = 1 probe_points = [[970, 173], [1039, 168]] framecnt = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) print(framecnt) print("<style> body { background-color: black; } td { width: 20px; height: 1px; } </style>") print("<table style=\"border-collapse: collapse;\">") for frame_number in range(0, framecnt, frame_skip): video.set(1, frame_number) # Read the frame success, frame = video.read() newsize = (int(frame.shape[1] / frame_decimation), int(frame.shape[0] / frame_decimation)) resized = cv2.resize(frame, newsize, interpolation = cv2.INTER_AREA) # Get the color of the pixel at the given location cols = [] for point in probe_points: (b, g, r) = resized[int(point[1]/frame_decimation), int(point[0] / frame_decimation)] cols.append(f"#{r:02X}{g:02X}{b:02X}") #print("\t".join(cols)) print("<tr>" + "".join(map(lambda x : f"<td style=\"background-color: {x}\"> </td>", cols)) + "</tr>") print("</table>") video.release() </source> Bei Videomaterial mit 25 fps (was zugegebenermaßen etwas wenig ist), sieht ein etwas längerer Ausschnitt des Videos oben wie folgt aus: <gallery> ff_rebooter_xiaomi_start.png | Start des Xiaomi-Routers </gallery> Links, wie im Video oben, die Power-LED, rechts die Link-LED. Wie aus dem Quellcode ersichtlich sein sollte, entspricht bei frame_skip = 1 jedes Frame ein Pixel in y-Richtung bei 25 fps. "Misst" man die Pixel vom ersten Lebenszeichen der linken LED bis sie blau wird, "vergehen" 1840 Pixel und somit 73,6 s - nicht ganz. Weil HTML ist das was man eingibt nicht unbedingt das, was angezeigt wird. Laut Konsole ist jeder oben angegebene Pixel 2px in der Darstellung, somit beträgt die Boot-Zeit 36,8 s. Der Bootloop ist nicht spektakulärer, er ist lediglich die immerwährende Wiederholung des "orangen" Parts. =Umsetzung= ==Hardware== Der erste Gedanke war, die Hardware minimalinvasiv aufzubauen: Nachdem es Dauerlicht nur gibt, wenn die Kiste läuft, ist die Farbe irrelevant. Blinkt etwas länger, ist etwas im Argen. Also warum nicht einfach einen Fototransistor anflanschen, die Helligkeit auswerten und wenn längeres Blinken herrscht denk Anker werfen? Es scheitert wie immer an der Realität. Die ersten Versuche waren aussichtsreich, mit Umgebungslicht und nicht exakt platziertem Fototransistor war die Freude aber recht schnell wieder vorbei. Für die ersten Versuche auf dem Breadboard hat es zumindest gereicht. Um nicht extra Teile bestellen zu müssen, wurde das eingeplant, was herum liegt, Herzstück ist ein (völlig überdimensionierter) ATmega8A, der Signale zweier Fototransistoren im SMD-Package, aber auch in der THT-Version in Form von BPW40 entgegennimmt. Um beide LEDs am Router erfassen zu können, sind diese im Abstand von 15 mm zueinander platziert. Auf der anderen Seite des Mikrocontrollers hängen p-Kanal FETs sowohl im SO-8- als auch SOT-23-Gehäuse, über die die Versorgung des Routers geschaltet wird. Um evtl. doch noch einen UART mit abweichender Spannung (und Domäne) anbinden zu können, noch zwei einfache Levelshifter dazu und ab auf eine Leiterkarte damit. Noch zwei Status-LEDs dazu und fertig ist der Lack. Recht viel Optionales, aber eine zweiten Leiterkarten-Spin zu fahren: #gerkeinbock Leiterkarten-Spin? Ja, mittlerweile bin ich echt zu faul, etwas auf Lochraster aufzubauen - zumal so gut wie alle Bauteile im SMD-Package daherkommen. Der zusammengeklöppelte Schaltplan, Layout und der Aufbau sehen wie folgt aus: <gallery> ff_rebooter_sch.png | Schaltplan ff_rebooter_pcb.png | Layout der Leiterkarte ff_rebooter_pcb_top.jpg | Bestückte Oberseite ff_rebooter_pcb_bot.jpg | Bestückte Unterseite </gallery> ===BOM & Nachbau=== Nachdem die Hardware schnell-schnell zusammengeklöppelt wurde, ist aktuell keine BOM und genauere Details vorgesehen. Wer sie dennoch möchte, kann sie gerne aus den EAGLE-Daten erzeugen oder mich anschreiben. ==Firmware== Die Software hat im Prinzip nur eine Aufgabe: Blinkt die Power LED länger als x Sekunden, wird die Stromversorgung für y Sekunden unterbrochen. "Genau das, nur etwas komplizierter!" Zunächst gilt die Frage zu klären: Wann blinkt was, wann ist es statisch an, wann aus? ===ADC=== Vorher muss aber erst noch geklärt werden: Wann ist eine LED überhaupt an? Mit den vorhin erwähnten Fototransistoren muss man das Umgebungslicht filtern. Ist die LED länger statisch und das Licht "außenrum" ändert sich, oder es verrutscht etwas leicht, verpasst man vielleicht, dass sich etwas ändert. Kann man filtern, kann man aber auch von Grund auf vermeiden. auch wenn die Elektronik dafür vorgesehen ist: man muss die optischen Sensoren nicht verwenden, sondern kann auch einfach auf die Ansteuerung der LEDs gehen. Diese erfolgt jedoch nicht mit boardähnlichen 5 V, sondern mit 3,3 V, was für die Eingänge etwas knapp werden kann. Also kommt doch der ADC zum Einsatz, wenn auch etwas vereinfacht: zwei Schwellenwerte, dazwischen eine Hysterese, fertig. Einen Schritt zurück: Der Analog zu Digital-Wandler durchläuft, nachdem das "Subsystem" getriggert wurde alle ausgewählten Kanäle, was etwa jede Millisekunde geschieht. Schwellenwertvergleich und ab mit einem true oder false in die LED-Detektion. ===LED-Detektion=== Diese schaut, ob sich was am Zustand des Einganges ändert und zählt die entsprechende Zeit. Wechselt der Zustand nach "0" (false) wird erst einmal blinkend angenommen, bleibt der Zustand für länger als <code>LEDDET_TIMEOUT</code> (750 ms) konstant, wird "statisch aus" respektive "an" angenommen. Das Ganze wird für die rote und blaue LED der "Power-LED" gemacht... ===Zustandsautomat=== ... und im "Target"-Zustandsautomaten verwurstet, der zunächst auf Papier entstand und nach der Implementierung auf dem PC nachgezeichnet wurde: <gallery> ff_rebooter_fsm.png | Zustandsautomat für das "Target" </gallery> Nach dem Einschalten geht die Maschine zunächst in den Off-Zustand - hauptsächlich um die Realität abzubilden. Beim Startup wird die Stromversorgung für den Router eingeschaltet und die grüne LED blinkt vor sich hin. Sobald für länger als 2 Sekunden die orange LED des Routers erloschen ist und die blaue leuchtet, wird angenommen dass der Router läuft. Ist das nach 90 Sekunden am Strom nicht der Fall, wird ein Crash angenommen und ein harter Reboot eingeleitet (mehr dazu später). Im Zustand Running gibt es zwei Varianten für die eigenen Status-LEDs: In jedem Fall leuchtet die grüne LED dauerhaft, wurde vorher ein Crash "erkannt", blitzt zusätzlich die rote LED auf. Sollte nun am Router die orange LED an gehen oder blinken und die die blaue LED nicht an sein, gibt es einen Crashverdacht; allerdings erst, wenn dies für über 2 Sekunden mit "Waterlevel" der Fall ist. Mit Waterlevel ist gemeint, dass im "Verdachtszustand" ein Zähler hochgezählt wird. Ist der "Verdacht" vorbei, wird dieser Zähler nicht auf Null zurückgesetzt, sondern lediglich verringert. So kann ein instabiler Zustand etwas besser erkannt werden. Erhärtet sich der Crashverdacht, wird ein interner Zähler für die Verdachtsfälle hochgezählt, erreicht dieser die magische Anzahl 3 oder bleibt der Zustand für über 90 Sekunden, wird ein Neustart eingeleitet. "Fängt" sich der Router wieder, sprich: die blaue LED leuchtet konstant und die orange ist aus, wechselt der Zustand nach 5 Sekunden wieder nach Running. Allerdings hier ohne Waterlevel. Lieber einen harten Neustart als im Limbus zwischen Running und Crashed hängen bleiben. Da beim erhärteten Crashverdacht vermutlich nix mehr geht, darf nun die rote Status-LED blinken, die grüne bleibt dunkel. Beim Durchführen des Reboots wird die Stromversorgung zum Router unterbrochen und die rote Status-LED blinkt schnell. Nach 5 Sekunden beginnt der Lebenszyklus des Routers von Vorne (Off) und er darf wieder starten. Wozu der Aufwand? Der Router startet zwar recht schnell (etwa 40 Sekunden reine Bootzeit), benötigt im dümmsten Fall aber 1-2 Minuten, bis er wieder mit dem Freifunk-Netz verbunden ist. Daher sollen unnötige Reboots vermieden werden. Warum aber so lange Wartezeiten, bevor der Strom abgedreht wird? Auch hier: Vorsicht. Es gibt auch legitime Gründe, warum der Router einen "Crash" hinlegt. Dieser lässt sich nicht von einem (gewollten) Neustart unterscheiden, sei es ein Admin aus der Ferne oder ein Firmware-Update. Gerade letzteres sollte man nicht durch einen harten Neustart unterbrechen. Nach einem Test dauert der erste Start nach einem Update unter 90 Sekunden, mal hoffen, dass sich das auch so im Feld verhält - schließlich sitzen die Bewohner nicht gerne ohne Internet und ich stehe ungern vor verschlossenen Türen, wenn es etwas zu tun gibt. Damit nicht der Mikrocontroller zum Problemfall wird, ist der interne Watchdog permanent aktiviert und wird (mehr oder weniger sinnvoll) im Mainloop zurückgesetzt. ==Einbau== Dafür, dass nach erstem Plan ein 3D-Druck-Gehäuse auf den Router geklebt werden sollte, hat sich ein fast idealer Platz im Gehäuse selbst gefunden - und auch für die Integration hatte Xiaomi ein Herz für Bastler. Oder zumindest beschlossen, dass ein 0-Ohm-Widerstand (R752) als Sicherung reicht. Mit dem nicht genutzten Verpolschutz (D12) gibt es auch ein Massepad direkt nebenan: <gallery> ff_rebooter_xiaomi_input.jpg | Eingangsbeschaltung am Router </gallery> An dieser Stelle sei angemerkt, dass man sicherlich auch den Enable/Shutdown-Pin des/der Regler hätte verwenden können, bei der unbekannten Beschaltung und den Widerständen im 0201-Gehäuse wawr es mir allerdings zu fummelig, dort einzugreifen. Den LEDs sieht man es mit scharfem Auge schon an, welche die orange und welche die blaue sein muss (wenn auch nicht unbedingt im Foto): Blaue LEDs haben (wie weiße) üblicherweise 2 Bond-Drähte, der ideale Abgriffpunkt ist zwischen Vorwiderstand und Kondensator: <gallery> ff_rebooter_router_leds.jpg | Status-LEDs am Router ff_rebooter_router_leds_detail.jpg | Detail-Ansicht der Dual-LED ff_rebooter_router_leds_beschaltung.jpg | Abgriffpunkte für die LEDs </gallery> Auf- und Eingebaut sieht es dann wie folgt aus: <gallery> ff_rebooter_xiaomi_einbau.jpg | Einbau des Rebooters im Router </gallery> Im Foto fehlt noch der obligatorische Heißkleber. Der Kondensator des Implantates musste noch ein bisschen gebogen werden, damit er nicht mit dem Gehäusedeckel kollidiert. Die abgeschnittenen Drähte sind ein Überbleibsel der oben erwähnten Logging-Aktivitäten (und wurden noch gestutzt). Die verbaute supergrüne LED ist trotz niedrigem Strom recht hell - sie ist, obwohl nach unten gerichtet, durch das Gehäuse leicht sichtbar und projiziert einen deutlichen Lichtkeil unter den gelöcherten Gehäuseboden. Kann man auch als Feature betrachten. =Das Ergebnis= Die ersten Tests mit per Konsole abgesetzten Reboots und einem erzwungenen Update waren erfolgreich - bei der Gelegenheit wurde auch gleich die Debug-Ausgaben eines Lebenszyklus (leider ohne Timestamps) aufgezeichnet: <pre> Built on: Apr 2 2023 21:47:12 Target: off -> off Target: off -> startup LED or: blinking LED bl: blinking LED bl: off LED or: on LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: startup finished Target: startup -> running Target: running, saw 0 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: recovered from crash state, saw 1 crashes Target: crashed -> running Target: running, saw 1 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: recovered from crash state, saw 2 crashes Target: crashed -> running Target: running, saw 2 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed Target: saw 3 crashes, reboot Target: crashed -> reboot LED bl: on Target: reboot -> off Target: off -> startup LED or: blinking LED bl: blinking LED bl: off LED or: on LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: startup finished Target: startup -> running Target: running, saw 0 crashes </pre> Patient 1 ist zum Zeitpunkt der Erstellung dieses Artikels seit 7 Tagen im Einsatz, legte erst einmal einen Lauf von knapp 5 Tagen hin und brauchte dann in etwa in etwa alle 12-17 Stunden einen Tritt. Router 2 ist erst seit kurzer Zeit wieder am Netz und hat kurz nach dem Start mutmaßlich einen Crash auf dem anderen Router verursacht - zumindest gab es eine verdächtige Korrelation zwischen Einschalten von Router 2 und einem Crash von Router 1. Bei beiden Geräten wurden die Cronjobs für den nächtlichen Reboot deaktiviert. Andere Faktoren die Abstürze begünstigen sind mir aktuell nicht bekannt - bei beiden Geräten habe ich vor der Wiederinbetriebnahme ein Update erzwungen, bei einem auch manuell Caches geleert. Vielleicht bringt das was, vielleicht auch nicht. Auch gilt es noch WLAN-Mesh auf zumindest einem der Geräte zu deaktivieren, zumal beide über Kabel angebunden sind und Komplexität sicherlich nicht zur Stabilität beitragen. =Ausblick= Die Schaltung kann verkleinert und optimiert werden, alles Unnötige entfernt werden. Hintergedanke für den Levelshifter an der UART-Schnittstelle war, über die Menge an Ausgaben (oder Keywords) einen Absturz zu erkennen oder auch Rückmeldungen z. B. per HTTP-Request auf die Konsole zu injizieren. Geschadet hat das Vorsehen sicher nicht, dank der bisherigen Zuverlässigkeit der aktuellen Erkennungsmethode und Statistik-Tools von ffmuc ist das aber nicht nötig. Wenn die Geräte etwas länger wieder im Betrieb sind, wird es ein Update geben. Generell halte ich einen externen Watchdog für Geräte, auf die man keinen permanenten Zugriff hat, für essenziell. Besser wäre natürlich, wenn es gar nicht bräuchte - was ich nicht als Kritik an [https://ffmuc.net/ Freifunk München]/[https://github.com/freifunk-gluon/gluon Gluon]/[https://openwrt.org/ OpenWRT] meine. Die Projekte leben überwiegend von freiwilligen, die in ihrer Freizeit und Community mehr bewegen als manch kommerzielle Anbieter. =Downloads= * [[ff_rebooter_v0.1.zip]] Schaltplan & Layout im EAGLE-Format und Firmware als Microchip-Studio-Projekt [[Kategorie:AVR]] [[Kategorie:Netzwerk]] 977fe4fc2955c7ef957a138390ab978715ebc47b 1856 1855 2023-04-11T20:18:12Z Chris 2 /* Downloads */ wikitext text/x-wiki =Ausgangssituation= In unseren Flüchtlingsunterkünften stehen mehrere Xiaomi Mi Router 4A Gigabit Edition, die mit der Freifunk-München-Firmware bespielt sind. Wer Freifunk nicht kennt, kann und sollte am besten sich in der [[wpde:Freifunk|Wikipedia]] informieren. Was am Anfang noch recht gut funktionierte, wurde mit der Zeit immer instabiler. Ein Cronjob zum nächtlichen Neustart brachte zwar Besserung, aber nach ein paar Tagen gingen die Router in eine Bootloop. Um den Fehler besser zu verstehen, wurde zeitweise ein [https://hobbyelektronik.org/b/2022/10/uart-logging-mit-linux/ Raspberry Pi zum Protokollieren] abgestellt. Als jemand, der von Linux nur rudimentäres Wissen besitzt, sahen die Meldungen so aus, als könne der SoC einen der WLAN-Chips nicht mehr initialisieren und schoss sich ins Nirwana. Blöd: ein Reboot richtet das nicht, Dokumentation für die Chips hängt wohl hinter der NDA-Mauer und einen hard-reset scheint es nicht zu geben. Nach einem kurzen Austausch im Chat der Freifunker gab es ein Ticket bei OpenWRT und nach einigen paar Tagen auch eine Experimental-Firmware, die den Fehler beheben sollte. Sollte. Ein paar Tage später stand bei Grafana für die Knoten wieder "no data", dafür gab es Klagen aus der Unterkunft. Einer der Router steht hinter für die dauerhaft verschlossener Tür, der andere in einem Zimmer dessen Bewohner auch mal ein paar Tage nicht da sind (und absperren). =Lösungsansätze= Kurz den/die entsprechenden LS-Schalter zu werfen ist leider auch keine Option. Das genauere Warum habe ich nicht weiter hinterfragt, das muss man einfach als gegeben annehmen. Dabei ist Strom trennen einfach wie effektiv. Eine Zeitschaltuhr würde helfen, die billigeren haben aber recht grobe Zeitraster und dementsprechend lange Ausfallzeiten. Auch kann es natürlich gleich nach einem Zwangsneustart gleich wieder zu Problemen kommen und die Wartezeit zum nächsten Neustart wird unnötig lang. Zwischenstecker mit Tasmota o. ä. würden zwar das Problem mit der Ausschaltzeit lösen, hätten aber wenig Chancen gegen Problem 2. Zwar könnten diese checken, ob das WLAN wegfällt, die Unterkunft wird allerdings durch mehrere Freifunk-Router (mit gleicher SSID) versorgt. Unnötig viel Komplexität. =Die Idee= Man sieht es den Routern von außen an, wenn sie abschmieren – im Betrieb leuchtet die Power-LED permanent blau, bei einem Crash bzw. Bootloop blinkt sie orange vor sich hin. Mit ein bisschen Mustererkennung erkennt man sogar die Phasen. Warum also nicht einen kleinen Mikrocontroller auf die Status-LED(s) schauen lassen und das "have you tried to turn it off and on again"-Spiel spielen lassen? ==Datensammeln== Am Anfang war die Beobachtung: In einem kleinen WhatsApp-Video bekam ich das unheilvolle orange blinken von einem Vereinsmitglied; ein paar Sekunden sind jedoch noch nicht die ganze Geschichte, deshalb holte ich mir einen der Router nach Hause und nahm ein Video von einem Kaltstart des Gerätes auf und wartete ein bisschen. Ein paar Tage am Netz und siehe da: ohne Zutun von außen blinkt die Power-LED orange. Also nochmal die Kamera raus, Aufnahme und einige Minuten laufen lassen. Als Referenz gab es dann noch ein Video von einem erfolgreichen Start: [[Datei:ff_rebooter_xiaomi_start.mp4]] Mit den Videos kann man sich die Mäusedisco nun wieder und wieder ansehen, Bild für Bild durchgehen und die Blinkzyklen aufschreiben, oder man ist faul und fragt ChatGPT, wie man mit Python die Farben von Pixeln in Videos ermittelt. Ok, das ist wirklich keine rocket science (und einfach nur in der Doku von OpenCV zu stöbern hätte gereicht), aber schon erstaunlich, was Wortstatistik auf Steroiden leisten kann. ==Videoauswertung== Für den ersten Eindruck ist die Herangehensweise eher unakademisch - das Beispiel vom Chatbot wird angepasst, damit an zwei Punkten - Power- und Link-LED - die Farben ermittelt werden, diese werden als Zellenhintergrund für eine HTML-Tabelle ausgegeben. Einfach wie fatal. Um nicht nur einen Pixel zu sampeln, wird jeder Frame um den Faktor 16 dezimiert - statt 1280x720 wird also ein Bild der Größe 80x45 verwendet. Das macht den Prozess nicht schneller, dafür werden Rauschen und Überstrahlungseffekte etwas reduziert. <source lang="python"> import cv2 video = cv2.VideoCapture("S1040005.MP4") frame_decimation = 16 frame_skip = 1 probe_points = [[970, 173], [1039, 168]] framecnt = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) print(framecnt) print("<style> body { background-color: black; } td { width: 20px; height: 1px; } </style>") print("<table style=\"border-collapse: collapse;\">") for frame_number in range(0, framecnt, frame_skip): video.set(1, frame_number) # Read the frame success, frame = video.read() newsize = (int(frame.shape[1] / frame_decimation), int(frame.shape[0] / frame_decimation)) resized = cv2.resize(frame, newsize, interpolation = cv2.INTER_AREA) # Get the color of the pixel at the given location cols = [] for point in probe_points: (b, g, r) = resized[int(point[1]/frame_decimation), int(point[0] / frame_decimation)] cols.append(f"#{r:02X}{g:02X}{b:02X}") #print("\t".join(cols)) print("<tr>" + "".join(map(lambda x : f"<td style=\"background-color: {x}\"> </td>", cols)) + "</tr>") print("</table>") video.release() </source> Bei Videomaterial mit 25 fps (was zugegebenermaßen etwas wenig ist), sieht ein etwas längerer Ausschnitt des Videos oben wie folgt aus: <gallery> ff_rebooter_xiaomi_start.png | Start des Xiaomi-Routers </gallery> Links, wie im Video oben, die Power-LED, rechts die Link-LED. Wie aus dem Quellcode ersichtlich sein sollte, entspricht bei frame_skip = 1 jedes Frame ein Pixel in y-Richtung bei 25 fps. "Misst" man die Pixel vom ersten Lebenszeichen der linken LED bis sie blau wird, "vergehen" 1840 Pixel und somit 73,6 s - nicht ganz. Weil HTML ist das was man eingibt nicht unbedingt das, was angezeigt wird. Laut Konsole ist jeder oben angegebene Pixel 2px in der Darstellung, somit beträgt die Boot-Zeit 36,8 s. Der Bootloop ist nicht spektakulärer, er ist lediglich die immerwährende Wiederholung des "orangen" Parts. =Umsetzung= ==Hardware== Der erste Gedanke war, die Hardware minimalinvasiv aufzubauen: Nachdem es Dauerlicht nur gibt, wenn die Kiste läuft, ist die Farbe irrelevant. Blinkt etwas länger, ist etwas im Argen. Also warum nicht einfach einen Fototransistor anflanschen, die Helligkeit auswerten und wenn längeres Blinken herrscht denk Anker werfen? Es scheitert wie immer an der Realität. Die ersten Versuche waren aussichtsreich, mit Umgebungslicht und nicht exakt platziertem Fototransistor war die Freude aber recht schnell wieder vorbei. Für die ersten Versuche auf dem Breadboard hat es zumindest gereicht. Um nicht extra Teile bestellen zu müssen, wurde das eingeplant, was herum liegt, Herzstück ist ein (völlig überdimensionierter) ATmega8A, der Signale zweier Fototransistoren im SMD-Package, aber auch in der THT-Version in Form von BPW40 entgegennimmt. Um beide LEDs am Router erfassen zu können, sind diese im Abstand von 15 mm zueinander platziert. Auf der anderen Seite des Mikrocontrollers hängen p-Kanal FETs sowohl im SO-8- als auch SOT-23-Gehäuse, über die die Versorgung des Routers geschaltet wird. Um evtl. doch noch einen UART mit abweichender Spannung (und Domäne) anbinden zu können, noch zwei einfache Levelshifter dazu und ab auf eine Leiterkarte damit. Noch zwei Status-LEDs dazu und fertig ist der Lack. Recht viel Optionales, aber eine zweiten Leiterkarten-Spin zu fahren: #gerkeinbock Leiterkarten-Spin? Ja, mittlerweile bin ich echt zu faul, etwas auf Lochraster aufzubauen - zumal so gut wie alle Bauteile im SMD-Package daherkommen. Der zusammengeklöppelte Schaltplan, Layout und der Aufbau sehen wie folgt aus: <gallery> ff_rebooter_sch.png | Schaltplan ff_rebooter_pcb.png | Layout der Leiterkarte ff_rebooter_pcb_top.jpg | Bestückte Oberseite ff_rebooter_pcb_bot.jpg | Bestückte Unterseite </gallery> ===BOM & Nachbau=== Nachdem die Hardware schnell-schnell zusammengeklöppelt wurde, ist aktuell keine BOM und genauere Details vorgesehen. Wer sie dennoch möchte, kann sie gerne aus den EAGLE-Daten erzeugen oder mich anschreiben. ==Firmware== Die Software hat im Prinzip nur eine Aufgabe: Blinkt die Power LED länger als x Sekunden, wird die Stromversorgung für y Sekunden unterbrochen. "Genau das, nur etwas komplizierter!" Zunächst gilt die Frage zu klären: Wann blinkt was, wann ist es statisch an, wann aus? ===ADC=== Vorher muss aber erst noch geklärt werden: Wann ist eine LED überhaupt an? Mit den vorhin erwähnten Fototransistoren muss man das Umgebungslicht filtern. Ist die LED länger statisch und das Licht "außenrum" ändert sich, oder es verrutscht etwas leicht, verpasst man vielleicht, dass sich etwas ändert. Kann man filtern, kann man aber auch von Grund auf vermeiden. auch wenn die Elektronik dafür vorgesehen ist: man muss die optischen Sensoren nicht verwenden, sondern kann auch einfach auf die Ansteuerung der LEDs gehen. Diese erfolgt jedoch nicht mit boardähnlichen 5 V, sondern mit 3,3 V, was für die Eingänge etwas knapp werden kann. Also kommt doch der ADC zum Einsatz, wenn auch etwas vereinfacht: zwei Schwellenwerte, dazwischen eine Hysterese, fertig. Einen Schritt zurück: Der Analog zu Digital-Wandler durchläuft, nachdem das "Subsystem" getriggert wurde alle ausgewählten Kanäle, was etwa jede Millisekunde geschieht. Schwellenwertvergleich und ab mit einem true oder false in die LED-Detektion. ===LED-Detektion=== Diese schaut, ob sich was am Zustand des Einganges ändert und zählt die entsprechende Zeit. Wechselt der Zustand nach "0" (false) wird erst einmal blinkend angenommen, bleibt der Zustand für länger als <code>LEDDET_TIMEOUT</code> (750 ms) konstant, wird "statisch aus" respektive "an" angenommen. Das Ganze wird für die rote und blaue LED der "Power-LED" gemacht... ===Zustandsautomat=== ... und im "Target"-Zustandsautomaten verwurstet, der zunächst auf Papier entstand und nach der Implementierung auf dem PC nachgezeichnet wurde: <gallery> ff_rebooter_fsm.png | Zustandsautomat für das "Target" </gallery> Nach dem Einschalten geht die Maschine zunächst in den Off-Zustand - hauptsächlich um die Realität abzubilden. Beim Startup wird die Stromversorgung für den Router eingeschaltet und die grüne LED blinkt vor sich hin. Sobald für länger als 2 Sekunden die orange LED des Routers erloschen ist und die blaue leuchtet, wird angenommen dass der Router läuft. Ist das nach 90 Sekunden am Strom nicht der Fall, wird ein Crash angenommen und ein harter Reboot eingeleitet (mehr dazu später). Im Zustand Running gibt es zwei Varianten für die eigenen Status-LEDs: In jedem Fall leuchtet die grüne LED dauerhaft, wurde vorher ein Crash "erkannt", blitzt zusätzlich die rote LED auf. Sollte nun am Router die orange LED an gehen oder blinken und die die blaue LED nicht an sein, gibt es einen Crashverdacht; allerdings erst, wenn dies für über 2 Sekunden mit "Waterlevel" der Fall ist. Mit Waterlevel ist gemeint, dass im "Verdachtszustand" ein Zähler hochgezählt wird. Ist der "Verdacht" vorbei, wird dieser Zähler nicht auf Null zurückgesetzt, sondern lediglich verringert. So kann ein instabiler Zustand etwas besser erkannt werden. Erhärtet sich der Crashverdacht, wird ein interner Zähler für die Verdachtsfälle hochgezählt, erreicht dieser die magische Anzahl 3 oder bleibt der Zustand für über 90 Sekunden, wird ein Neustart eingeleitet. "Fängt" sich der Router wieder, sprich: die blaue LED leuchtet konstant und die orange ist aus, wechselt der Zustand nach 5 Sekunden wieder nach Running. Allerdings hier ohne Waterlevel. Lieber einen harten Neustart als im Limbus zwischen Running und Crashed hängen bleiben. Da beim erhärteten Crashverdacht vermutlich nix mehr geht, darf nun die rote Status-LED blinken, die grüne bleibt dunkel. Beim Durchführen des Reboots wird die Stromversorgung zum Router unterbrochen und die rote Status-LED blinkt schnell. Nach 5 Sekunden beginnt der Lebenszyklus des Routers von Vorne (Off) und er darf wieder starten. Wozu der Aufwand? Der Router startet zwar recht schnell (etwa 40 Sekunden reine Bootzeit), benötigt im dümmsten Fall aber 1-2 Minuten, bis er wieder mit dem Freifunk-Netz verbunden ist. Daher sollen unnötige Reboots vermieden werden. Warum aber so lange Wartezeiten, bevor der Strom abgedreht wird? Auch hier: Vorsicht. Es gibt auch legitime Gründe, warum der Router einen "Crash" hinlegt. Dieser lässt sich nicht von einem (gewollten) Neustart unterscheiden, sei es ein Admin aus der Ferne oder ein Firmware-Update. Gerade letzteres sollte man nicht durch einen harten Neustart unterbrechen. Nach einem Test dauert der erste Start nach einem Update unter 90 Sekunden, mal hoffen, dass sich das auch so im Feld verhält - schließlich sitzen die Bewohner nicht gerne ohne Internet und ich stehe ungern vor verschlossenen Türen, wenn es etwas zu tun gibt. Damit nicht der Mikrocontroller zum Problemfall wird, ist der interne Watchdog permanent aktiviert und wird (mehr oder weniger sinnvoll) im Mainloop zurückgesetzt. ==Einbau== Dafür, dass nach erstem Plan ein 3D-Druck-Gehäuse auf den Router geklebt werden sollte, hat sich ein fast idealer Platz im Gehäuse selbst gefunden - und auch für die Integration hatte Xiaomi ein Herz für Bastler. Oder zumindest beschlossen, dass ein 0-Ohm-Widerstand (R752) als Sicherung reicht. Mit dem nicht genutzten Verpolschutz (D12) gibt es auch ein Massepad direkt nebenan: <gallery> ff_rebooter_xiaomi_input.jpg | Eingangsbeschaltung am Router </gallery> An dieser Stelle sei angemerkt, dass man sicherlich auch den Enable/Shutdown-Pin des/der Regler hätte verwenden können, bei der unbekannten Beschaltung und den Widerständen im 0201-Gehäuse wawr es mir allerdings zu fummelig, dort einzugreifen. Den LEDs sieht man es mit scharfem Auge schon an, welche die orange und welche die blaue sein muss (wenn auch nicht unbedingt im Foto): Blaue LEDs haben (wie weiße) üblicherweise 2 Bond-Drähte, der ideale Abgriffpunkt ist zwischen Vorwiderstand und Kondensator: <gallery> ff_rebooter_router_leds.jpg | Status-LEDs am Router ff_rebooter_router_leds_detail.jpg | Detail-Ansicht der Dual-LED ff_rebooter_router_leds_beschaltung.jpg | Abgriffpunkte für die LEDs </gallery> Auf- und Eingebaut sieht es dann wie folgt aus: <gallery> ff_rebooter_xiaomi_einbau.jpg | Einbau des Rebooters im Router </gallery> Im Foto fehlt noch der obligatorische Heißkleber. Der Kondensator des Implantates musste noch ein bisschen gebogen werden, damit er nicht mit dem Gehäusedeckel kollidiert. Die abgeschnittenen Drähte sind ein Überbleibsel der oben erwähnten Logging-Aktivitäten (und wurden noch gestutzt). Die verbaute supergrüne LED ist trotz niedrigem Strom recht hell - sie ist, obwohl nach unten gerichtet, durch das Gehäuse leicht sichtbar und projiziert einen deutlichen Lichtkeil unter den gelöcherten Gehäuseboden. Kann man auch als Feature betrachten. =Das Ergebnis= Die ersten Tests mit per Konsole abgesetzten Reboots und einem erzwungenen Update waren erfolgreich - bei der Gelegenheit wurde auch gleich die Debug-Ausgaben eines Lebenszyklus (leider ohne Timestamps) aufgezeichnet: <pre> Built on: Apr 2 2023 21:47:12 Target: off -> off Target: off -> startup LED or: blinking LED bl: blinking LED bl: off LED or: on LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: startup finished Target: startup -> running Target: running, saw 0 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: recovered from crash state, saw 1 crashes Target: crashed -> running Target: running, saw 1 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: recovered from crash state, saw 2 crashes Target: crashed -> running Target: running, saw 2 crashes LED bl: blinking LED bl: off LED or: on Target: running -> crashed Target: saw 3 crashes, reboot Target: crashed -> reboot LED bl: on Target: reboot -> off Target: off -> startup LED or: blinking LED bl: blinking LED bl: off LED or: on LED or: blinking LED or: off LED or: blinking LED or: off LED bl: on Target: startup finished Target: startup -> running Target: running, saw 0 crashes </pre> Patient 1 ist zum Zeitpunkt der Erstellung dieses Artikels seit 7 Tagen im Einsatz, legte erst einmal einen Lauf von knapp 5 Tagen hin und brauchte dann in etwa in etwa alle 12-17 Stunden einen Tritt. Router 2 ist erst seit kurzer Zeit wieder am Netz und hat kurz nach dem Start mutmaßlich einen Crash auf dem anderen Router verursacht - zumindest gab es eine verdächtige Korrelation zwischen Einschalten von Router 2 und einem Crash von Router 1. Bei beiden Geräten wurden die Cronjobs für den nächtlichen Reboot deaktiviert. Andere Faktoren die Abstürze begünstigen sind mir aktuell nicht bekannt - bei beiden Geräten habe ich vor der Wiederinbetriebnahme ein Update erzwungen, bei einem auch manuell Caches geleert. Vielleicht bringt das was, vielleicht auch nicht. Auch gilt es noch WLAN-Mesh auf zumindest einem der Geräte zu deaktivieren, zumal beide über Kabel angebunden sind und Komplexität sicherlich nicht zur Stabilität beitragen. =Ausblick= Die Schaltung kann verkleinert und optimiert werden, alles Unnötige entfernt werden. Hintergedanke für den Levelshifter an der UART-Schnittstelle war, über die Menge an Ausgaben (oder Keywords) einen Absturz zu erkennen oder auch Rückmeldungen z. B. per HTTP-Request auf die Konsole zu injizieren. Geschadet hat das Vorsehen sicher nicht, dank der bisherigen Zuverlässigkeit der aktuellen Erkennungsmethode und Statistik-Tools von ffmuc ist das aber nicht nötig. Wenn die Geräte etwas länger wieder im Betrieb sind, wird es ein Update geben. Generell halte ich einen externen Watchdog für Geräte, auf die man keinen permanenten Zugriff hat, für essenziell. Besser wäre natürlich, wenn es gar nicht bräuchte - was ich nicht als Kritik an [https://ffmuc.net/ Freifunk München]/[https://github.com/freifunk-gluon/gluon Gluon]/[https://openwrt.org/ OpenWRT] meine. Die Projekte leben überwiegend von freiwilligen, die in ihrer Freizeit und Community mehr bewegen als manch kommerzielle Anbieter. =Downloads= * [[Datei:ff_rebooter_v0.1.zip]] Schaltplan & Layout im EAGLE-Format und Firmware als Microchip-Studio-Projekt [[Kategorie:AVR]] [[Kategorie:Netzwerk]] d445fddb480bc3c546791fa6c04a3e7721c79fa7 Datei:Ff rebooter v0.1.zip 6 829 1857 2023-04-11T20:18:26Z Chris 2 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Hauptseite 0 1 1858 1829 2023-04-11T20:20:48Z Chris 2 /* Neues & Änderungen */ wikitext text/x-wiki '''Willkommen auf hobbyelektronik.org!''' Auf diesen Seiten findest du [[Hobbyelektronik.org:Impressum|unsere]] Projekte rund um Elektronik und allem möglichen, was uns interessiert. Neben dem Wiki hier gibt es auch ein '''[//hobbyelektronik.org/b/ Blog]''', das sich nicht nur mit Elektronik und der Homepage beschäftigt. Dort kann - im Gegensatz zum Wiki hier - auch fleißig kommentiert werden, was an dieser Stelle aufgrund von massivem Spam deaktiviert werden musste. Aber nun wünsche ich viel Spaß beim stöbern auf den Seiten hier! Bitte benutze die Navigation links, um zu den [[Spezial:Alle Seiten|Artikeln]] zu kommen. =[//hobbyelektronik.org/b/ Blog]= <WPPlatest /> =Neues & Änderungen= <div id="mw-latest-changes10"> *11.04.2023 Pünktlich zu Ostern wird ein paar [[Freifunk-Rebooter|Freifunk-Routern]] in die... - ach, lassen wir das. *24.11.2022 Beim VBus-ESP8266-Adapter kann es [[VBus-Decoder/Adapter_für_den_ESP8266#Fehlerhafter_Datenempfang|Fehler beim Datenempfang]] geben *22.11.2022 Kleine Korrektur beim [[VBus-Decoder/Adapter_für_RS-232|VBus-Adapter für RS-232]] *11.11.2022 Weitere Informationen zu den [[Prozeda-Decoder#Display|Displaydaten]] beim [[Prozeda-Decoder]] *10.11.2022 Ein CitrinSolar CS 1.3 wurde [[Resol_-_Zerlegt#CitrinSolar_CS_1.3|zerlegt]] und [[Resol - Reparaturen|repariert]] *02.11.2022 Ein [[Resol 71005014 Schnittstellenadapter]] wurde repariert und verbessert *02.11.2022 Warum zur Abwechslung nicht einmal paar [[Resol - Zerlegt|Resol Geräte zerlegen]] *23.12.2021 Es wird heimelig zu Weihnachten: ein [[LED-Lagerfeuer]] *13.12.2021 Mal wieder ein VBus-Decoder - jetzt für den [[VBus-Decoder/Adapter_für_den_ESP8266|ESP8266]] *07.09.2021 Eine aktualisierte Untersuchung des [[ECL-Bus-Protokoll]]s *12.07.2021 Der Pythoncode der [[MCP-USB-Bridge]] ist auf GitHub umgezogen und spricht nun mit dem MCP2210 (SPI) *26.02.2021 Und noch ein Update für den VBus-Decoder: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Die Enttäuschung - Teil 2| Version 1.2b]] und [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]], sowie einem einfachen [[VBus-Decoder#Protokoll-Analysator|Protokoll-Analysator]] *09.02.2021 Die Artikel [[VBus-Decoder]] und [[Prozeda-Decoder]] sind nun in Unterseiten aufgeteilt *10.05.2020 Mit irgendwelchen Tasten OBS steuern: [[Anykey x6]] *08.04.2020 Etwas für den Drucker: [[3D-Druck-Sammelsurium#Mikrofonarm_f.C3.BCr_den_Zoom_H2n|Mikrofonarm für den Zoom H2n]] *04.04.2020 [[Reparatur_R%26S_CMU200_Hintergrundbeleuchtung|Ein neues Backlight für eine CMU200]] *31.03.2020 Es geht auch günstiger: [[VBus-Decoder/Adapter_für_den_Raspberry_Pi#Kostenreduzierte_Variante.2Fv1.2|Costdown für den VBus-Decoder am Raspberry Pi]] *10.03.2020 Wer braucht es nicht: einen [[USB-Fußtaster]] *15.02.2020 Ein bisschen Modellpflege: [[MCP-USB-Bridge#USB-I.C2.B2C-Bridge_v1.1|MCP USB-I²C-Bridge v1.1]], ein [[VBus-Decoder/Adapter_Nano|VBus-Adapter für den Raspberry Pi]] und die VBus-Boards Nano-Boards sind wieder da :) *19.01.2020 [[Pirozeda]] Version 0.4 hat wohl Stabilitätsprobleme *19.01.2020 Update für die [[MCP-USB-Bridge|MCP2221-Python-Lib]] und Anmerkungen zu Datenblattfehlern *13.01.2020 Backplates für den [[3D-Druck-Sammelsurium#Diamex_AVR-Prog_Bodenplatte|Diamex AVR-Prog]] und die [[3D-Druck-Sammelsurium#USB-I.C2.B2C-Bridge_Bodenplatte|MCP USB-I²C-Bridge]] im [[3D-Druck-Sammelsurium]] *25.12.2019 [[3D-Druck-Sammelsurium]] *16.12.2019 Ein paar [[Softwaretools|Tools]] um die [[Softwaretools#SerialPlayer|serielle Schnittstelle zu bespaßen]] und [[Softwaretools#SaleaeTools|Daten aus Saleae Logic komfortabler verarbeiten zu können]] *10.11.2019 Für den VBus-Adapter Nano gibt es nun einen [[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting-Guide]] und eine [[VBus-Decoder#Python-Implementierung|Python-Implementierung]] *17.09.2019 Für den MCP2221 und MCP2210 (USB I²C- & SPI-Interface) gibt es nun eine [[MCP-USB-Bridge#C.23-Lib|C#-Lib]] *07.05.2019 Ein Adapter für den Adapter: Der [[Atmel-ICE-Adapter]] *21.03.2019 Doku des [[Pirozeda-HAT]] korrigiert & aktualisiert *16.03.2019 Ein paar Infos und ein mechanischer Adapter für [[Ikea Trådfri]] (teilweise aus dem Blog übernommen) *11.02.2019 Der [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] ist nun aufgebaut und getestet *10.02.2019 Der [[EAGLE-BOM]]-Export kann nun auch JSON *03.01.2019 Auch für den VBus gibt es neue Hardware: [[VBus-Decoder/Adapter_Nano|VBus-Adapter Nano]] *03.01.2019 Langsam wird ein Hut draus: Der [[Pirozeda#Pirozeda-HAT|Pirozeda-HAT]] ist zwar noch nicht da, aber bald. *27.10.2018 [[MCP-USB-Bridge#Python-Lib|MCP-USB-Bridge]] es gibt nun eine Python-Lib, die die meisten Features des MCP2221 unterstützt *23.08.2018 [[MCP-USB-Bridge]] - billiges und einfaches I²C- & SPI-Interface für den PC *19.08.2018 EAGLE kann nun direkt [[EAGLE-BOM_für_MediaWiki|BOMs als MediaWiki-Tabelle]] exportieren *05.08.2018 [[Pirozeda]] Version 0.31. ...und nochmal ein Bugfix. Die Aktualisierung für die aktuellen Daten/Display und Statistik wurden nicht richtig aktualisiert *05.08.2018 [[Pirozeda]] Version 0.3. Ein paar Bugfixes und ein 3D-Diagramm für historische Daten *16.04.2018 Im Artikel des [[Prozeda-Decoder]] gibt es nun [[Prozeda-Decoder#Einblick_in_den_Regler|Einblick in den Regler]] *15.04.2018 Der [[Prozeda-Decoder]] ist nun mit einem Raspberry Pi verheiratet: [[Pirozeda]] *12.11.2017 [[Mini-LED-Treiber]] *17.04.2017 Update von MediaWiki, mehr im [//hobbyelektronik.org/b/?p=1556 Blog] *22.02.2017 Solaranlagen von Wagner-Solar bzw. [[Prozeda-Decoder|Prozeda]] können nun ausgelesen werden *31.12.2016 Dank [[Briefkasteninnenbeleuchtung]] ist mein Briefkasten innen beleuchtet *11.03.2016 Kleines Update für den [[VBus-Decoder]]: Es gibt nun [[VBus-Decoder/Adapter_für_RS-232|Hardware für den PC]] *19.04.2015 Ein Nachtrag bei der [[Kühlung_für_Zhongdi_ZD-939L#Nachtrag_19.04.2015|Kühlung für Zhongdi ZD-939L]] *10.04.2015 [[ASCII-Tabelle]]: Dez- & Hex-Angaben deutlicher, neue Druckformate. *10.05.2014 Neu: [[Kühlung für Zhongdi ZD-393L]] *02.02.2014 Neu: [[EAGLE-Bibliotheken]] *10.11.2013 Neu: [[Zeitraffer mit Linux]] *20.10.2013 [[EMR7370]] korrigiert. In main() war ein falscher Funktionsaufruf. *14.08.2013 Neu: [[Umbau Belkin Auto-USB-Lader]] *02.05.2013 Neu: [[Farnell-Assistent]] *16.01.2013 Neu: [[Halbleiterelektronik-Formelsammlung]] *11.10.2012 Neu: [[EAGLE-Toolbar]] *26.09.2012 Neu: [[Sony Dimmer]] *05.05.2012 Neu: [[Raspberry Pi IO]] *28.04.2012 [[EMR7370]] ergänzt. Der Quellcode ist nun verfügbar. *14.03.2012 Ein paar Bilder zum [[Kameratimer]] und dem [[SNES-Joypad]] hinzugefügt *12.03.2012 Neu: [[EMR7370]] *29.12.2011 Neu: [[Polizeiauto]] *03.10.2011 Neu: [[Audioslave]] *13.09.2011 Neu: [[Modellbau-Leuchtstofflampe]] *12.09.2011 Neu: [[Gartenbrunnen]] *12.06.2011 Neu: [[Maschinenleuchte]] *04.05.2011 Neu: [[ECL-Bus-Decoder]] *19.03.2011 [[What's next?]]: Zimmerbus *19.03.2011 Neu: [[Physik-Formelsammlung]] *15.01.2011 Neu: [[Belichtungsgeraet]] *09.12.2010 Neu: [[Energieerfassung/Solarleistung]] *21.11.2010 [[What's next?]]: Ein paar Infos zum Moodlight *21.11.2010 [[AVR-Doper]]: "Patch" für AVR-Studio *21.11.2010 [[Energieerfassung]]: Abschnitt [[Energieerfassung#Nerviges/Todo|Todo/Nerviges]] hinzugefügt *15.11.2010 [[Energieerfassung#Downloads|Energieerfassung ? Downloads]]: Die Firmware steht jetzt zum Download bereit *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüllt *10.10.2010 Neu: [[Kameratimer]] *10.10.2010 [[Energieerfassung#Solaranlage|Energieerfassung ? Solaranlage]]: Die PT1000 haben nun doch ihren Zweck erfüll *31.08.2010 Neu: [[Energieerfassung]] *09.08.2010 Neu: [[AVR-NET-IO-Shield]] *15.07.2010 Neu: [[Nokia 5110 Displayadapter]] *09.07.2010 Neu: [[Sommerhitz]] *16.06.2010 Seiten in [[:Kategorie:AVR|Kategorie AVR]]: AVR Infobox hinzugefügt *13.06.2010 [[Touchlight]] (Abschnitt [[Touchlight#Praxis|Praxis]] hinzugefügt) *19.03.2010 [[What's next?]]: Zimmerbus *04.03.2010 Neu: [[VBus-Decoder]] *04.03.2010 [[SNES-Joypad]] (Autocal-Version & ATtiny2313-Version) *24.02.2010 Neu: [[UnitColor]] *12.02.2010 Neu: [[Panasonic-Zapper]] *09.01.2010 Neu: [[ASCII-Tabelle]] *27.12.2009 Neu: [[USBLotIO]] *04.07.2009 Neu: [[Touchlight]] *19.01.2009 Neu: [[Datenlogger]] *01.09.2008 Neu: [[Labornetzteil]] *09.08.2008 Neu: [[Cursor]] *08.08.2008 Neu: [[Image Resizer]] *14.03.2008 Neu: [[Platinenbohrmaschine]] <html><a id="showall" href="#Neues_.26_.C3.84nderungen" onclick="document.getElementById('mw-latest-changes10').className='all';">Alle Änderungen anzeigen</a></html> </div> a5774e70575cfc3daf07288f10243b1d96c33ebb Datei:Vbusesp vbusonly pinout.png 6 744 1859 1709 2023-06-17T20:58:28Z Chris 2 Chris lud eine neue Version von [[Datei:Vbusesp vbusonly pinout.png]] hoch wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder/Adapter für den ESP8266 0 757 1860 1828 2023-06-17T21:00:15Z Chris 2 /* Decoder */ wikitext text/x-wiki [[Bild:vbusesp_top.jpg|thumb|Aufgebauter Leiterkarte (v0.1)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Wenn Basteln und IoT aufeinandertreffen, kommt man fast nicht an den Mikrocontrollern von Espressif vorbei. Genau aus diesem Grund hatte ich schon länger die Idee, ein Leiterkärtchen mit dem ESP8266 zu machen. Also warum nicht einfach den beliebten VBus ohne großes Strippenziehen ins Netzwerk bringen? =Schaltung= Die Schaltung für den VBus basiert auf der für den [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Raspi (v1.3)]], aufseiten des ESP habe ich mich von den verschiedenen Bastelboards inspirieren lassen und die Möglichkeit vorgesehen, sowohl die kleinen ESP01- als auch die etwas vielseitigeren ESP12-Module einzusetzen. Die Versorgung findet über eine Stiftleiste (bzw. angelötete Drähte) oder über eine Micro-USB-Buchse statt. Diese dient nur der Stromversorgung - mehr zum Programmieren des ESP weiter unten. Bei der Verwendung des ESP12-Moduls stehen zusätzlich zum VBus-Interface noch die GPIOs 12, 13, 14 und 16 sowie der ADC-Eingang und die 3,3V-Versorgung zur Verfügung. Hier kann weitere Peripherie wie Sensoren oder Displays angeschlossen werden. Für den Aufbau gibt es mehrere Varianten, die unten aufgeführt sind. Diese können über die Tabs ausgewählt und müssen beim Besorgen der Bauteile und selbstverständlich beim Zusammenbau kombiniert werden. Die theoretische Maximalbestückung sieht wie folgt aus: <gallery> vbusesp_max_sch_1.png | Schaltplan VBus + Stromversorgung vbusesp_max_sch_2.png | Schaltplan ESP8266 und IO vbusesp_max_assy.png | Bestückungsplan </gallery> =BOM= Möglichkeiten schaffen Komplexität. Wie bei den anderen Plattformen lässt sich der Adapter in verschiedenen Varianten aufbauen, wobei ich (auch wenn es gerade bei dieser anbietet) noch immer empfehle, die Optoisolierte aufzubauen. ==Decoder== Neben Optoisoliert und Direkt gibt es noch die Variante ohne ESP - dank der Stiftleiste rechts oben auf der Leiterkarte lässt sich der VBus-Anteil komplett unabhängig vom ESP-Anteil verwenden. Mit Säge und Fingerspitzengefühl lässt sich die Größe auch noch ein gutes Stück reduzieren. Als ESP8266-Modul kann das ESP01 und ESP12(-F) verwendet werden. Getestet wurde bis jetzt nur das ESP12-F, wobei nichts gegen das 01 sprechen dürfte. <tabs> <tab name="Optoisoliert"> Empfohlene Bestückungsvariante. <gallery> vbusesp_optiso_sch_1.png | Variantenschaltplan VBus vbusesp_optiso_sch_2.png | Variantenschaltplan ESP8266 vbusesp_optiso_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 5 || R9, R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Direkt"> <gallery> vbusesp_direct_sch_1.png | Variantenschaltplan VBus vbusesp_direct_sch_2.png | Variantenschaltplan ESP8266 vbusesp_direct_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 4 || R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 2 || Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Optoisoliert (ohne ESP)"> Wer keinen ESP8266 verwenden aber die Vorzüge der verbesserten Schaltung haben möchte, kann den ESP-Anteil vollständig weglassen. Hierfür wird auf dieser Leiterkarte keine Stromversorgung benötigt, da diese vom jeweilig verwendeten Interface (z. B. SBC, USB-UART-Wandler, ...) bezogen werden kann. <gallery> vbusesp_optisonoesp_sch_1.png | Variantenschaltplan VBus vbusesp_optisonoesp_sch_2.png | Variantenschaltplan Interface vbusesp_optisonoesp_assy.png | Bestückungsplan vbusesp_vbusonly_pinout.png | Anschlussbelegung des UART </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> Egal welche Variante aufgebaut wird: bitte nicht vergessen, den Jumper (statt des 0R-Widerstandes kann auch eine Lötbrücke gesetzt werden) zu löten. ==Stromversorgung== Für die Stromversorgung gibt es ebenfalls zwei Möglichkeiten: Entweder mit LDO oder Schaltwandler. Wer auf Nummer sicher gehen will, nimmt die billigere LDO-Variante, da ich noch keine Gelegenheit hatte letztere zu testen. Die etwas höhere Stromaufnahme dürfte wahrscheinlich nicht allzu sehr ins Gewicht fallen. <tabs> <tab name="Linearregler"> Empfohlene Bestückungsvariante. <gallery> vbusesp_vregldo_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregldo_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || REG1117 || SOT223 || NCP 1117 ST33T3G |} </tab> <tab name="Schaltwandler"> <gallery> vbusesp_vregsmps_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregsmps_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C9 || 100n || C0603 || X7R-G0603 100N |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C12 || 10p || C0603 || NPO-G0603 10P |- | 1 || R17 || 15k || R0603 || RND 0603 1 15K |- | 1 || L1 || 15u || 242408FPS || L-242408FPS 15µ |- | 1 || R16 || 47k || R0603 || RND 0603 1 47K |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || D6 || BAT43WS || SOD323-W || BAT 43WS |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || IC2 || MCP16301 || SOT23-6 || MCP 16301T-I/CHY |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || D4 || SS13L || SUBSMA || SS 13L |} </tab> </tabs> =Inbetriebnahme/Benutzung= ==Flashing== Wird ein ESP8266 verwendet, muss natürlich erst einmal die Software auf den Mikrocontroller. Das Problem: Der Softwaredownload findet über den selben UART statt, der auch für das VBus-Interface statt. Nun könnte man mit Multiplexern arbeiten, was im Idealfall nur einmal benutzt werden würde und somit mit Kanonen auf Spatzen geschossen wäre. Aus dem gleichen Grund gibt es keinen USB-UART-Konverter auf dem Board: Braucht nur Platz und kostet. Deshalb wird für das erstmalige Flashen ein USB-UART-Adapter, der RTS/DTR anbietet, benötigt. Dieser sollte idealerweise mit 3,3 V arbeite, wobei der ESP wohl auch 5 V toleriert. Die beiden Transistoren für Reset und Bootloader nach WittyCloud/NodeMCU sind bereits vorhanden. Die 5 V-Stromversorgung muss entweder über den USB-Port oder der Stiftleiste SV2 kommen, die Anschlussbelegung des UART an SV4 ist wie folgt: {| class="wikitable" ! Pin || Signal vom UART-Adapter |- | 1 || DTR |- | 3 || TX |- | 7 || RX |- | 9 || RTS |} <gallery> vbusesp_prog_1.png | Anschlussbelegung für das Programmieren per UART vbusesp_prog_2.jpg | Verwendung des WittyCloud-USB-Wandlers </gallery> Liegt das Trägerboard eines WittyCloud herum, müssen DTR und RTS gefädelt werden. ==Betrieb== Ist die Firmware auf dem Chip und es sollen Daten vom VBus decodiert werden, muss ein Jumper zwischen Pin 3 und 4 an SV4 oder ein Lötpunkt auf SJ1 gesetzt werden: <gallery> vbusesp_txjumper.png | UART-Verbindung zwischen VBus und ESP8266 </gallery> =Firmware= Zugegebenermaßen: ich habe zwar seit Jahren ein paar ESP8266-Module herumliegen, mich aber nie so richtig damit auseinandergesetzt. Aber das macht nichts: [https://tasmota.github.io/docs/ Tasmota] unterstützt verschiedene [https://tasmota.github.io/docs/Smart-Meter-Interface/ Smart Metering]-Anbindungen, für die die Firmware allerdings angepasst selbst kompiliert werden muss. Michael hat sich (mit der Unterstützung aus der Tasmota-Community) daran gemacht und freundlicherweise die nötigen Anpassungen zur Verfügung gestellt: Folgendes muss in der Datei <code>tasmota/user_config_override.h</code> ergänzt werden: <source lang="C"> #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ #ifndef USE_SCRIPT #define USE_SCRIPT #endif #ifndef USE_SML_M #define USE_SML_M #endif #ifdef USE_RULES #undef USE_RULES #endif #ifndef SML_REPLACE_VARS #define SML_REPLACE_VARS #endif #ifndef USE_SML_SCRIPT_CMD #define USE_SML_SCRIPT_CMD #endif #ifndef SML_MAX_VARS #define SML_MAX_VARS 20 #endif #ifndef USE_SCRIPT_JSON_EXPORT #define USE_SCRIPT_JSON_EXPORT #endif #ifndef USE_SCRIPT_WEB_DISPLAY #define USE_SCRIPT_WEB_DISPLAY #endif </source> ==Konfiguration== Nach dem Flashen des Mikrocontrollers, was für fertige Builds auch über den Tasmotizer erfolgen kann, kann unter <code>Main-Menu -> Console -> Edit Script</code> das [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus Script ergänzt] werden. Mit dem Befehl <code>sensor53 d1</code> kann man den Header für die [https://tasmota.github.io/docs/Smart-Meter-Interface/#meter-metrics Meter Metrics] ermitteln und im Script entsprechend anpassen. Für die RemaSol B/2 sieht das wie folgt aus: <source> r="1,aa10005d101000010a67" coltemp=0 Byte1=0 Byte2=0 >S coltemp=sml[1] Byte1=coltemp>>8 Byte2=coltemp&0xff if Byte1==0x00 { coltemp=coltemp&0xff } if Byte1==0xff { coltemp=(coltemp-0x10000) } coltemp=coltemp*0.1 >B =>sensor53 r >M 1 +1,3,v,0,9600,Solar %r%vo0uw@1,KollektorBase,°C,kolbase,2 %r%vo0uw@10,KollektorOrg,°C,kolorg,2 %r%vo2uw@10,Speicher unten,°C,spu,1 %r%vo4uw@10,Speicher oben,°C,spo,1 %r%vo8ub@1,Pumpe,%%,pump,0 # >J ,"Calculated":{"kol":%coltemp%} >W Kollektor berechnet: {m} %coltemp% °C </source> Anmerkung: Hierbei handelt es sich um einen direkten Copy & Paste aus Michaels Script. Je nach Konfiguration der Anlage kann es Abweichungen geben. Um den Fragen zuvorzukommen - die Anpassung auf die Jeweilige Anlage beginnt in der ersten Zeile: <code> r="1,<span class="hb1">aa</span><span class="hb2">1000</span><span class="hb3">5d10</span><span class="hb4">10</span><span class="hb5">0001</span><span class="hb6">0a</span><span class="hb7">67</span>" </code> Die Farben entsprechen dem Beispiel von der [[VBus-Decoder#Protokoll|Artikelhauptseite]], kurzum: * <span class="hb1">aa</span>: Sync-Wort * <span class="hb2">1000</span>: Zieladresse * <span class="hb3">5d10</span>: Quelladresse * <span class="hb4">10</span>: Protokollversion * <span class="hb5">0001</span>: Befehl * <span class="hb6">0a</span>: Anzahl Nutzdatenframes * <span class="hb7">67</span>: Prüfsumme Die <span class="hb3">Quelladresse</span> kann in der [https://danielwippermann.github.io/resol-vbus/#/vsf VBus-Spezifikation nachgeschlagen werden]. Zu beachten ist hier die Endianness: was in der Doku als <code>0x1234</code> geschrieben ist, muss hier als <code>3412</code> angegeben werden. Anschließend muss man auf der [https://danielwippermann.github.io/resol-vbus/#/vsf oben genannten Seite] nach dem Command 0x0100 für den entsprechenden Regler suchen. Dazu am besten oben nach 0x0100 filtern und dann mit Strg+F die Quelladresse finden. Klickt man in der Zeile auf <code>Bytes</code> bekommt man die Länge der Nachricht, wobei man 1 addieren muss, da es sich um Offsets handelt. Beim RemaSol 1/2 (bzw. DeDietrich Sol Plus ER 709) ist der größte Offset 39, also 40 Bytes. Mit dem Wissen, dass ein Frame 4 Byte enthält, ergibt sich eine Länge von 10 Frames, was einem Hexadezimalwert von <span class="hb6">0x0A</span> entspricht. Nun muss man nur noch die Prüfsumme berechnen (oder durch Schnüffeln am UART ermitteln) Für die Feldzuordnung lohnt sich ein scharfer Blick und Vergleich der <code>Fields</code>-Seite für die [https://danielwippermann.github.io/resol-vbus/#/vsf/fields/00_0010_4221_10_0100 DeltaSol BS Plus] und dem Beispiel in der [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus dieses Reglers] in der Tasmota-Doku. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. Achtung: Es handelt sich um Version 0.1, auf der sich 3 kleine Fehler befinden, die sich allerdings mit Fädeldraht korrigieren lassen: ==Hotfix für v0.1== Um die Leiterkarte Version 0.1 korrekt nutzen zu können, sind bis zu 3 Fixes nötig: ===Bootloader-Schaltung=== Die Beschaltung der Transistoren ist teilweise falsch. Um dies zu korrigieren, müssen 3 Leiterbahnen aufgetrennt werden und die Verbindungen mit Fädeldraht neu hergestellt werden. Das Auftrennen kann je nach Geschmack mit einem kleinen Trennschleifer (Vulgo Dremel) oder einem Messer erfolgen. Statt der zwei Drähte zum unteren der beiden Widerstände kann der Widerstand (im 0603-Gehäuse) auch zwischen die beiden Pads am Transistor gelegt werden und damit ein Schnitt und eine Drahtverbindung gespart werden. <gallery> vbusesp_v01fix_transistor_rewire.png | Korrekturanleitung vbusesp_v01fix_transistor_prep1.jpg | mit dem Skalpell entfernt vbusesp_v01fix_transistor_prep2.jpg | mit dem Trennschleifer durchtrennt vbusesp_v01fix_transistor_done.jpg | Durchgeführte Korrektur </gallery> ===Beschaltung GPIO15 am ESP12=== Diese Korrektur ist nur relevant, wenn man ein ESP12-Modul einsetzt. Der Mikrocontroller startet nur, wenn GPIO15 über einen Pull-down mit Masse verbunden ist. Dazu sollte ein 10k-Widerstand zwischen diese beiden Pins, wie unten dargestellt, eingebaut werden: <gallery> vbusesp_v01fix_res.jpg | Durchgeführte Korrektur. Widerstand ist zweckvoll! </gallery> ===Pull-up an Q3=== Wird die Tx-Funktionalität verwendet, blockiert der als Pull-down eingesetzte R14 den Bus. Um dies zu berichtigen muss das linke Pad getrennt und mit und mit VBUS_3V3 verbunden werden: <gallery> vbusesp_v01fix_tx_pull.png | Korrekturanleitung </gallery> =Bekannte Probleme= ==Fehlerhafter Datenempfang== Carsten hat eine interessante Entdeckung bei seinem Aufbau gemacht, untersucht und dann auch gleich eine Lösung gefunden: <pre> Nachdem ich den VBus Dekoder programmiert hatte, ist mir aufgefallen, dass die gesamte Kommunikation sehr stark mit Bitfehlern behaft ist. Nur etwa ein Drittel der VBus Frames kamen unversehrt in der Software an; das Ende langer Pakete war so gut wie immer kaputt. Wenn ich einen FTDI USB Konverter hinter den Optokoppler gehängt habe, wurden die Daten fehlerfrei auf dem PC empfangen, also musste das Problem mit dem ESP zusammenhängen. Daher habe ich mir in den UART Treiber einen Debug-Pin eingebaut, der bei jedem Frame-Fehler mein DSO getriggert hat und das war dann zu sehen: </pre> <gallery> Vbusesp_carsten_rx_issue_1.png | Oszi-Screenshot mit defekter und korrekter Nachricht </gallery> <pre> Irgendwie hat der ESP RX Eingang unter bestimmten Umständen den Pin so stark nach VCC gezogen, dass die Pegel kaputt gegangen sind. Warum er das scheinbar nur manchmal macht, ist mir allerdings noch immer ein Rätsel. Dann weiter im Sourcecode gesucht, wo die Pin-Konfiguration während der Initialisierung des UART gemacht wird. Hier bin ich dann in der Datei 'core_esp8266_wiring_digital.cpp' fündig geworden: </pre> <gallery> Vbusesp_carsten_rx_issue_2.png | Codestelle des Fixes </gallery> <pre> Seitdem ich die Zeile 42 unschädlich gemacht habe, läuft die Kommunikation wie geschnitten Brot :-) Der Debug-Trigger hat auch nach mehreren Stunden nicht mehr zugeschlagen. Ich muss jetzt noch dazu sagen, dass ich die Software mit PlatformIO entwickele uns ich die Version 4.0.1 des ESP8266 Platform Package aktuell verwende. Das kann gut sein, dass es mit anderen IDEs und anderen/älteren Packages nicht passiert, weil der Pullup dort nicht eingeschaltet wird. </pre> Wer die Stelle im Repo sucht: [https://github.com/esp8266/Arduino/blob/master/cores/esp8266/core_esp8266_wiring_digital.cpp#L41 hier ist sie]. Ich bin zwar kein großer Freund, tief in Libs zu patchen, konnte aber nach einem Abend Erstkontakt mit den Tasmota-Sourcen keinen besseren Ort für eine Anpassung finden. Bleibt die Frage, warum der Pull-up aktiviert und deaktiviert wird - bei einer (kurzen) Suche ist mir im Code nichts aufgefallen. Kann natürlich sein, dass die CPU selbst das entsprechende Bit setzt/löscht, was aber merkwürdig wäre. Bleiben zwei Optionen: entweder selber nochmal forschen oder einen Issue in Github erstellen. =Downloads= * [[Datei:Vbusesp_0.2.zip]] EAGLE-Dateien Adapter v0.2 für den ESP8266 ==Archiv== * [[Datei:Vbusesp_0.1.zip]] EAGLE-Dateien Adapter v0.1 für den ESP8266 [[Kategorie:ESP8266]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 572442d1f654146f5ba24b5d07286202b95e01f8 1868 1860 2023-08-25T20:33:12Z Chris 2 Hinweis zu ESPHome hinzugefügt wikitext text/x-wiki [[Bild:vbusesp_top.jpg|thumb|Aufgebauter Leiterkarte (v0.1)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Wenn Basteln und IoT aufeinandertreffen, kommt man fast nicht an den Mikrocontrollern von Espressif vorbei. Genau aus diesem Grund hatte ich schon länger die Idee, ein Leiterkärtchen mit dem ESP8266 zu machen. Also warum nicht einfach den beliebten VBus ohne großes Strippenziehen ins Netzwerk bringen? =Schaltung= Die Schaltung für den VBus basiert auf der für den [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Raspi (v1.3)]], aufseiten des ESP habe ich mich von den verschiedenen Bastelboards inspirieren lassen und die Möglichkeit vorgesehen, sowohl die kleinen ESP01- als auch die etwas vielseitigeren ESP12-Module einzusetzen. Die Versorgung findet über eine Stiftleiste (bzw. angelötete Drähte) oder über eine Micro-USB-Buchse statt. Diese dient nur der Stromversorgung - mehr zum Programmieren des ESP weiter unten. Bei der Verwendung des ESP12-Moduls stehen zusätzlich zum VBus-Interface noch die GPIOs 12, 13, 14 und 16 sowie der ADC-Eingang und die 3,3V-Versorgung zur Verfügung. Hier kann weitere Peripherie wie Sensoren oder Displays angeschlossen werden. Für den Aufbau gibt es mehrere Varianten, die unten aufgeführt sind. Diese können über die Tabs ausgewählt und müssen beim Besorgen der Bauteile und selbstverständlich beim Zusammenbau kombiniert werden. Die theoretische Maximalbestückung sieht wie folgt aus: <gallery> vbusesp_max_sch_1.png | Schaltplan VBus + Stromversorgung vbusesp_max_sch_2.png | Schaltplan ESP8266 und IO vbusesp_max_assy.png | Bestückungsplan </gallery> =BOM= Möglichkeiten schaffen Komplexität. Wie bei den anderen Plattformen lässt sich der Adapter in verschiedenen Varianten aufbauen, wobei ich (auch wenn es gerade bei dieser anbietet) noch immer empfehle, die Optoisolierte aufzubauen. ==Decoder== Neben Optoisoliert und Direkt gibt es noch die Variante ohne ESP - dank der Stiftleiste rechts oben auf der Leiterkarte lässt sich der VBus-Anteil komplett unabhängig vom ESP-Anteil verwenden. Mit Säge und Fingerspitzengefühl lässt sich die Größe auch noch ein gutes Stück reduzieren. Als ESP8266-Modul kann das ESP01 und ESP12(-F) verwendet werden. Getestet wurde bis jetzt nur das ESP12-F, wobei nichts gegen das 01 sprechen dürfte. <tabs> <tab name="Optoisoliert"> Empfohlene Bestückungsvariante. <gallery> vbusesp_optiso_sch_1.png | Variantenschaltplan VBus vbusesp_optiso_sch_2.png | Variantenschaltplan ESP8266 vbusesp_optiso_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 5 || R9, R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Direkt"> <gallery> vbusesp_direct_sch_1.png | Variantenschaltplan VBus vbusesp_direct_sch_2.png | Variantenschaltplan ESP8266 vbusesp_direct_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || SV3 || || MA07-1R || MPE 087-1-007 |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 1 || C11 || 100n || C0603 || X7R-G0603 100N |- | 3 || C2, C8, C14 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 4 || R18, R19, R22, R24 || 10k || R0805 || RND 0805 1 10K |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 4 || R20, R21, R25, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 1 || C10 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || S1 || 9305 || PHAP3301 || TASTER 9305 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 2 || T1, T2 || BC848 || SOT23 || BC 848B SMD |- | 2 || Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || U2 || ESP01 || ESP01 || DEBO ESP8266 |- | 1 || U1 || ESP12 || ESP12-SMD || DEBO ESP8266-12F |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} </tab> <tab name="Optoisoliert (ohne ESP)"> Wer keinen ESP8266 verwenden aber die Vorzüge der verbesserten Schaltung haben möchte, kann den ESP-Anteil vollständig weglassen. Hierfür wird auf dieser Leiterkarte keine Stromversorgung benötigt, da diese vom jeweilig verwendeten Interface (z. B. SBC, USB-UART-Wandler, ...) bezogen werden kann. <gallery> vbusesp_optisonoesp_sch_1.png | Variantenschaltplan VBus vbusesp_optisonoesp_sch_2.png | Variantenschaltplan Interface vbusesp_optisonoesp_assy.png | Bestückungsplan vbusesp_vbusonly_pinout.png | Anschlussbelegung des UART </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || SV4 || || MA05-2 || MPE 087-2-010 |- | 1 || JMP1 || 0R-JUMPA || A0R-JMP || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 1 || R1 || 12k || R0805 || RND 1550805 DP |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R9 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |} </tab> </tabs> Egal welche Variante aufgebaut wird: bitte nicht vergessen, den Jumper (statt des 0R-Widerstandes kann auch eine Lötbrücke gesetzt werden) zu löten. ==Stromversorgung== Für die Stromversorgung gibt es ebenfalls zwei Möglichkeiten: Entweder mit LDO oder Schaltwandler. Wer auf Nummer sicher gehen will, nimmt die billigere LDO-Variante, da ich noch keine Gelegenheit hatte letztere zu testen. Die etwas höhere Stromaufnahme dürfte wahrscheinlich nicht allzu sehr ins Gewicht fallen. <tabs> <tab name="Linearregler"> Empfohlene Bestückungsvariante. <gallery> vbusesp_vregldo_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregldo_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || J1 || || JUMP || JUMPER 2,54 SW |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || IC3 || REG1117 || SOT223 || NCP 1117 ST33T3G |} </tab> <tab name="Schaltwandler"> <gallery> vbusesp_vregsmps_sch_1.png | Variantenschaltplan Stromversorgung vbusesp_vregsmps_assy.png | Bestückungsplan </gallery> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 1 || C9 || 100n || C0603 || X7R-G0603 100N |- | 1 || C15 || 100n || C0805 || X7R-G0805 100N |- | 1 || C12 || 10p || C0603 || NPO-G0603 10P |- | 1 || R17 || 15k || R0603 || RND 0603 1 15K |- | 1 || L1 || 15u || 242408FPS || L-242408FPS 15µ |- | 1 || R16 || 47k || R0603 || RND 0603 1 47K |- | 1 || C13 || 47u/16V || PANASONIC_D || FK-V 47U 16 |- | 1 || D6 || BAT43WS || SOD323-W || BAT 43WS |- | 1 || SV2 || MA02-1R || MA02-1R || MPE 087-1-002 |- | 1 || IC2 || MCP16301 || SOT23-6 || MCP 16301T-I/CHY |- | 1 || X2 || MIUSB-F5M-BB-UHS || MIUSB-F5M-BB-U_HANDSOLDER || MIC USB BBU |- | 1 || D4 || SS13L || SUBSMA || SS 13L |} </tab> </tabs> =Inbetriebnahme/Benutzung= ==Flashing== Wird ein ESP8266 verwendet, muss natürlich erst einmal die Software auf den Mikrocontroller. Das Problem: Der Softwaredownload findet über den selben UART statt, der auch für das VBus-Interface statt. Nun könnte man mit Multiplexern arbeiten, was im Idealfall nur einmal benutzt werden würde und somit mit Kanonen auf Spatzen geschossen wäre. Aus dem gleichen Grund gibt es keinen USB-UART-Konverter auf dem Board: Braucht nur Platz und kostet. Deshalb wird für das erstmalige Flashen ein USB-UART-Adapter, der RTS/DTR anbietet, benötigt. Dieser sollte idealerweise mit 3,3 V arbeite, wobei der ESP wohl auch 5 V toleriert. Die beiden Transistoren für Reset und Bootloader nach WittyCloud/NodeMCU sind bereits vorhanden. Die 5 V-Stromversorgung muss entweder über den USB-Port oder der Stiftleiste SV2 kommen, die Anschlussbelegung des UART an SV4 ist wie folgt: {| class="wikitable" ! Pin || Signal vom UART-Adapter |- | 1 || DTR |- | 3 || TX |- | 7 || RX |- | 9 || RTS |} <gallery> vbusesp_prog_1.png | Anschlussbelegung für das Programmieren per UART vbusesp_prog_2.jpg | Verwendung des WittyCloud-USB-Wandlers </gallery> Liegt das Trägerboard eines WittyCloud herum, müssen DTR und RTS gefädelt werden. ==Betrieb== Ist die Firmware auf dem Chip und es sollen Daten vom VBus decodiert werden, muss ein Jumper zwischen Pin 3 und 4 an SV4 oder ein Lötpunkt auf SJ1 gesetzt werden: <gallery> vbusesp_txjumper.png | UART-Verbindung zwischen VBus und ESP8266 </gallery> =Firmware= Zugegebenermaßen: ich habe zwar seit Jahren ein paar ESP8266-Module herumliegen, mich aber nie so richtig damit auseinandergesetzt. ==Tasmota== Aber das macht nichts: [https://tasmota.github.io/docs/ Tasmota] unterstützt verschiedene [https://tasmota.github.io/docs/Smart-Meter-Interface/ Smart Metering]-Anbindungen, für die die Firmware allerdings angepasst selbst kompiliert werden muss. Michael hat sich (mit der Unterstützung aus der Tasmota-Community) daran gemacht und freundlicherweise die nötigen Anpassungen zur Verfügung gestellt: Folgendes muss in der Datei <code>tasmota/user_config_override.h</code> ergänzt werden: <source lang="C"> #ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ #ifndef USE_SCRIPT #define USE_SCRIPT #endif #ifndef USE_SML_M #define USE_SML_M #endif #ifdef USE_RULES #undef USE_RULES #endif #ifndef SML_REPLACE_VARS #define SML_REPLACE_VARS #endif #ifndef USE_SML_SCRIPT_CMD #define USE_SML_SCRIPT_CMD #endif #ifndef SML_MAX_VARS #define SML_MAX_VARS 20 #endif #ifndef USE_SCRIPT_JSON_EXPORT #define USE_SCRIPT_JSON_EXPORT #endif #ifndef USE_SCRIPT_WEB_DISPLAY #define USE_SCRIPT_WEB_DISPLAY #endif </source> ===Konfiguration=== Nach dem Flashen des Mikrocontrollers, was für fertige Builds auch über den Tasmotizer erfolgen kann, kann unter <code>Main-Menu -> Console -> Edit Script</code> das [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus Script ergänzt] werden. Mit dem Befehl <code>sensor53 d1</code> kann man den Header für die [https://tasmota.github.io/docs/Smart-Meter-Interface/#meter-metrics Meter Metrics] ermitteln und im Script entsprechend anpassen. Für die RemaSol B/2 sieht das wie folgt aus: <source> r="1,aa10005d101000010a67" coltemp=0 Byte1=0 Byte2=0 >S coltemp=sml[1] Byte1=coltemp>>8 Byte2=coltemp&0xff if Byte1==0x00 { coltemp=coltemp&0xff } if Byte1==0xff { coltemp=(coltemp-0x10000) } coltemp=coltemp*0.1 >B =>sensor53 r >M 1 +1,3,v,0,9600,Solar %r%vo0uw@1,KollektorBase,°C,kolbase,2 %r%vo0uw@10,KollektorOrg,°C,kolorg,2 %r%vo2uw@10,Speicher unten,°C,spu,1 %r%vo4uw@10,Speicher oben,°C,spo,1 %r%vo8ub@1,Pumpe,%%,pump,0 # >J ,"Calculated":{"kol":%coltemp%} >W Kollektor berechnet: {m} %coltemp% °C </source> Anmerkung: Hierbei handelt es sich um einen direkten Copy & Paste aus Michaels Script. Je nach Konfiguration der Anlage kann es Abweichungen geben. Um den Fragen zuvorzukommen - die Anpassung auf die Jeweilige Anlage beginnt in der ersten Zeile: <code> r="1,<span class="hb1">aa</span><span class="hb2">1000</span><span class="hb3">5d10</span><span class="hb4">10</span><span class="hb5">0001</span><span class="hb6">0a</span><span class="hb7">67</span>" </code> Die Farben entsprechen dem Beispiel von der [[VBus-Decoder#Protokoll|Artikelhauptseite]], kurzum: * <span class="hb1">aa</span>: Sync-Wort * <span class="hb2">1000</span>: Zieladresse * <span class="hb3">5d10</span>: Quelladresse * <span class="hb4">10</span>: Protokollversion * <span class="hb5">0001</span>: Befehl * <span class="hb6">0a</span>: Anzahl Nutzdatenframes * <span class="hb7">67</span>: Prüfsumme Die <span class="hb3">Quelladresse</span> kann in der [https://danielwippermann.github.io/resol-vbus/#/vsf VBus-Spezifikation nachgeschlagen werden]. Zu beachten ist hier die Endianness: was in der Doku als <code>0x1234</code> geschrieben ist, muss hier als <code>3412</code> angegeben werden. Anschließend muss man auf der [https://danielwippermann.github.io/resol-vbus/#/vsf oben genannten Seite] nach dem Command 0x0100 für den entsprechenden Regler suchen. Dazu am besten oben nach 0x0100 filtern und dann mit Strg+F die Quelladresse finden. Klickt man in der Zeile auf <code>Bytes</code> bekommt man die Länge der Nachricht, wobei man 1 addieren muss, da es sich um Offsets handelt. Beim RemaSol 1/2 (bzw. DeDietrich Sol Plus ER 709) ist der größte Offset 39, also 40 Bytes. Mit dem Wissen, dass ein Frame 4 Byte enthält, ergibt sich eine Länge von 10 Frames, was einem Hexadezimalwert von <span class="hb6">0x0A</span> entspricht. Nun muss man nur noch die Prüfsumme berechnen (oder durch Schnüffeln am UART ermitteln) Für die Feldzuordnung lohnt sich ein scharfer Blick und Vergleich der <code>Fields</code>-Seite für die [https://danielwippermann.github.io/resol-vbus/#/vsf/fields/00_0010_4221_10_0100 DeltaSol BS Plus] und dem Beispiel in der [https://tasmota.github.io/docs/Smart-Meter-Interface/#resol-deltasol-bs-plus-vbus dieses Reglers] in der Tasmota-Doku. ==ESPHome== Auch ESPHome hat eine [https://esphome.io/components/vbus.html VBus-Komponente], die nicht unerwähnt bleiben soll. Von Stephan habe ich den Bericht erhalten, dass er diese Kombination erfolgreich in Betrieb genommen hat - und dass es im Zusammenhang mit HomeAssistant auch für Einsteiger tauglich ist. Eine Änderung hat er jedoch an der Hardware vorgenommen: Statt Rx von VBus auf GPIO3 zu verbinden, hat er GPIO5 gewählt, damit GPIO5 für Logging verwendet werden kann. Wird dann wohl eine Bestückungsoption für die nächste Version der Hardware :) =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. Achtung: Es handelt sich um Version 0.1, auf der sich 3 kleine Fehler befinden, die sich allerdings mit Fädeldraht korrigieren lassen: ==Hotfix für v0.1== Um die Leiterkarte Version 0.1 korrekt nutzen zu können, sind bis zu 3 Fixes nötig: ===Bootloader-Schaltung=== Die Beschaltung der Transistoren ist teilweise falsch. Um dies zu korrigieren, müssen 3 Leiterbahnen aufgetrennt werden und die Verbindungen mit Fädeldraht neu hergestellt werden. Das Auftrennen kann je nach Geschmack mit einem kleinen Trennschleifer (Vulgo Dremel) oder einem Messer erfolgen. Statt der zwei Drähte zum unteren der beiden Widerstände kann der Widerstand (im 0603-Gehäuse) auch zwischen die beiden Pads am Transistor gelegt werden und damit ein Schnitt und eine Drahtverbindung gespart werden. <gallery> vbusesp_v01fix_transistor_rewire.png | Korrekturanleitung vbusesp_v01fix_transistor_prep1.jpg | mit dem Skalpell entfernt vbusesp_v01fix_transistor_prep2.jpg | mit dem Trennschleifer durchtrennt vbusesp_v01fix_transistor_done.jpg | Durchgeführte Korrektur </gallery> ===Beschaltung GPIO15 am ESP12=== Diese Korrektur ist nur relevant, wenn man ein ESP12-Modul einsetzt. Der Mikrocontroller startet nur, wenn GPIO15 über einen Pull-down mit Masse verbunden ist. Dazu sollte ein 10k-Widerstand zwischen diese beiden Pins, wie unten dargestellt, eingebaut werden: <gallery> vbusesp_v01fix_res.jpg | Durchgeführte Korrektur. Widerstand ist zweckvoll! </gallery> ===Pull-up an Q3=== Wird die Tx-Funktionalität verwendet, blockiert der als Pull-down eingesetzte R14 den Bus. Um dies zu berichtigen muss das linke Pad getrennt und mit und mit VBUS_3V3 verbunden werden: <gallery> vbusesp_v01fix_tx_pull.png | Korrekturanleitung </gallery> =Bekannte Probleme= ==Fehlerhafter Datenempfang== Carsten hat eine interessante Entdeckung bei seinem Aufbau gemacht, untersucht und dann auch gleich eine Lösung gefunden: <pre> Nachdem ich den VBus Dekoder programmiert hatte, ist mir aufgefallen, dass die gesamte Kommunikation sehr stark mit Bitfehlern behaft ist. Nur etwa ein Drittel der VBus Frames kamen unversehrt in der Software an; das Ende langer Pakete war so gut wie immer kaputt. Wenn ich einen FTDI USB Konverter hinter den Optokoppler gehängt habe, wurden die Daten fehlerfrei auf dem PC empfangen, also musste das Problem mit dem ESP zusammenhängen. Daher habe ich mir in den UART Treiber einen Debug-Pin eingebaut, der bei jedem Frame-Fehler mein DSO getriggert hat und das war dann zu sehen: </pre> <gallery> Vbusesp_carsten_rx_issue_1.png | Oszi-Screenshot mit defekter und korrekter Nachricht </gallery> <pre> Irgendwie hat der ESP RX Eingang unter bestimmten Umständen den Pin so stark nach VCC gezogen, dass die Pegel kaputt gegangen sind. Warum er das scheinbar nur manchmal macht, ist mir allerdings noch immer ein Rätsel. Dann weiter im Sourcecode gesucht, wo die Pin-Konfiguration während der Initialisierung des UART gemacht wird. Hier bin ich dann in der Datei 'core_esp8266_wiring_digital.cpp' fündig geworden: </pre> <gallery> Vbusesp_carsten_rx_issue_2.png | Codestelle des Fixes </gallery> <pre> Seitdem ich die Zeile 42 unschädlich gemacht habe, läuft die Kommunikation wie geschnitten Brot :-) Der Debug-Trigger hat auch nach mehreren Stunden nicht mehr zugeschlagen. Ich muss jetzt noch dazu sagen, dass ich die Software mit PlatformIO entwickele uns ich die Version 4.0.1 des ESP8266 Platform Package aktuell verwende. Das kann gut sein, dass es mit anderen IDEs und anderen/älteren Packages nicht passiert, weil der Pullup dort nicht eingeschaltet wird. </pre> Wer die Stelle im Repo sucht: [https://github.com/esp8266/Arduino/blob/master/cores/esp8266/core_esp8266_wiring_digital.cpp#L41 hier ist sie]. Ich bin zwar kein großer Freund, tief in Libs zu patchen, konnte aber nach einem Abend Erstkontakt mit den Tasmota-Sourcen keinen besseren Ort für eine Anpassung finden. Bleibt die Frage, warum der Pull-up aktiviert und deaktiviert wird - bei einer (kurzen) Suche ist mir im Code nichts aufgefallen. Kann natürlich sein, dass die CPU selbst das entsprechende Bit setzt/löscht, was aber merkwürdig wäre. Bleiben zwei Optionen: entweder selber nochmal forschen oder einen Issue in Github erstellen. =Downloads= * [[Datei:Vbusesp_0.2.zip]] EAGLE-Dateien Adapter v0.2 für den ESP8266 ==Archiv== * [[Datei:Vbusesp_0.1.zip]] EAGLE-Dateien Adapter v0.1 für den ESP8266 [[Kategorie:ESP8266]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] ba1b3389e9d622cf18e3cc7762d4c4d5e496fac9 Hobbyelektronik.org:Impressum 4 4 1861 1760 2023-06-17T21:01:34Z Chris 2 wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org For those who don't speak German: feel free to write me in English! Für Zuschriften auf deutsch: Das "du" wird bevorzugt :) Im Normalfall antworte ich innerhalb von 1-3 Tagen. Solltest du innerhalb einer Woche keine Antwort bekommen, prüfe bitte deinen Spamfilter oder schicke eine Erinnerung, manchmal geht auch bei mir etwas unter. E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] (oder auf sks-keyservers.net suchen) Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung im Schnitt nur eine Konversation in 2-3 Jahren verschlüsselt stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Kommerzielle Anfragen= In den meisten Fällen lautet die Antwort schlicht "Nein". Wie weiter unten steht habe ich kein Interesse an Werbung oder "kommerzieller Kooperation". Entsprechende Anfragen werden ignoriert. Auch habe ich wenig Interesse, in meiner Freizeit an kommerziellen Projekten oder Produkten zu arbeiten. Dazu fehlen mir einfach Zeit und Ressourcen. Nicht unbedingt technisch, sondern vielmehr organisatorisch. Produkte auf den Markt zu bringen ist deutlich mehr als Hardware zusammenzuklatschen und vielleicht noch "ein bisschen" Software dafür zu entwickeln. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über jede Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Bitte jedoch zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup sowie die verfügbaren Mittel in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schneller (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwende Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteh es einfach als Kompetenzübung und beachte den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nichts durch finanzielle Mittel beeinflusst. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird man beim genaueren Blick ins Blog oder ins Wiki bzw. hier im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich immer wieder geantwortet, dass sie das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen wie Freifunk sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich, kann aber zu Darstellungsfehlern führen. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) b4ad15d461572cef850906ad879dafc3e19d7e98 1862 1861 2023-06-17T21:03:29Z Chris 2 /* Kontakt */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org For those who don't speak German: feel free to write me in English! Für Zuschriften auf deutsch: Das "du" wird bevorzugt :) Im Normalfall antworte ich innerhalb von 1-3 Tagen. Solltest du innerhalb einer Woche keine Antwort bekommen, prüfe bitte deinen Spamfilter oder schicke eine Erinnerung, manchmal geht auch bei mir etwas unter. E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung im Schnitt nur eine Konversation in 2-3 Jahren verschlüsselt stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Kommerzielle Anfragen= In den meisten Fällen lautet die Antwort schlicht "Nein". Wie weiter unten steht habe ich kein Interesse an Werbung oder "kommerzieller Kooperation". Entsprechende Anfragen werden ignoriert. Auch habe ich wenig Interesse, in meiner Freizeit an kommerziellen Projekten oder Produkten zu arbeiten. Dazu fehlen mir einfach Zeit und Ressourcen. Nicht unbedingt technisch, sondern vielmehr organisatorisch. Produkte auf den Markt zu bringen ist deutlich mehr als Hardware zusammenzuklatschen und vielleicht noch "ein bisschen" Software dafür zu entwickeln. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über jede Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Bitte jedoch zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup sowie die verfügbaren Mittel in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schneller (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwende Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteh es einfach als Kompetenzübung und beachte den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nichts durch finanzielle Mittel beeinflusst. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird man beim genaueren Blick ins Blog oder ins Wiki bzw. hier im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich immer wieder geantwortet, dass sie das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen wie Freifunk sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich, kann aber zu Darstellungsfehlern führen. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) 51b398e4678cfe1a42d2aa9eb2ca9e176af23cda 1863 1862 2023-06-17T21:05:33Z Chris 2 /* Urheberrecht */ wikitext text/x-wiki =Angaben gemäß § 5 TMG= Diese Homepage wird betrieben durch: Christof Rueß<br /> St.-Wendelin-Str. 9<br /> 89264 Weißenhorn<br /> ==Kontakt== Bei Fragen bitte per E-Mail an mich wenden: E-Mail: chris at hobbyelektronik punkt org For those who don't speak German: feel free to write me in English! Für Zuschriften auf deutsch: Das "du" wird bevorzugt :) Im Normalfall antworte ich innerhalb von 1-3 Tagen. Solltest du innerhalb einer Woche keine Antwort bekommen, prüfe bitte deinen Spamfilter oder schicke eine Erinnerung, manchmal geht auch bei mir etwas unter. E-Mail via GPG: chris-crypt at hobbyelektronik punkt org [//hobbyelektronik.org/chris-crypt.asc Public Key] Bitte beachten: Wie die meisten bin ich kein aktiver Mailcrypto-User, zumal seit der Einrichtung im Schnitt nur eine Konversation in 2-3 Jahren verschlüsselt stattfindet. Die Wahrscheinlichkeit ist groß, dass ich erst mal wieder die Toolchain installieren und mich an das Passwort erinnern muss... Sollte E-Mail zur Kommunikation nicht ausreichen, kann auch eine Telefonnummer angefragt werden. Sollte dies nicht zwingend erforderlich sein, bitte ich jedoch Abstand davon zu nehmen. =Kommerzielle Anfragen= In den meisten Fällen lautet die Antwort schlicht "Nein". Wie weiter unten steht habe ich kein Interesse an Werbung oder "kommerzieller Kooperation". Entsprechende Anfragen werden ignoriert. Auch habe ich wenig Interesse, in meiner Freizeit an kommerziellen Projekten oder Produkten zu arbeiten. Dazu fehlen mir einfach Zeit und Ressourcen. Nicht unbedingt technisch, sondern vielmehr organisatorisch. Produkte auf den Markt zu bringen ist deutlich mehr als Hardware zusammenzuklatschen und vielleicht noch "ein bisschen" Software dafür zu entwickeln. =Fragen/Hilfe/Unterstützung= Bevor du eine Mail schreibst, bitte folgendes lesen und beachten: Ich mache das hier in meiner Freizeit und aus Spaß. Sollte es zu den Artikeln auf diesen Seiten Fragen, Hinweise oder Anmerkungen geben, freue ich mich über jede Mail. Genauso helfe ich - soweit es meine Zeit erlaubt - gerne, wenn es Probleme beim Auf- oder Nachbau oder Anpassung der hier vorgestellten Projekte gibt. Bitte jedoch zwei Dinge nicht zu verwechseln: Freie Hard-/Software und Freibier. Mir geht es darum, Wissen zu vermitteln und dich vorwärts zu bringen und nicht, dass du etwas "abgreifen" kannst. Ich kann dich nur unterstützen wenn du mir hilfst, dein Problem zu verstehen. Ich kenne dein Setup sowie die verfügbaren Mittel in aller Regel nicht und kann auch deine Fähigkeiten aus der Ferne meist nur sehr grob einschätzen. Deshalb ist es wichtig, dass du deinen Aufbau genau beschreibst (keine Salamitaktik!), meine Mails komplett liest und alle Fragen so weit wie möglich beantwortest - und nicht schon nach der ersten aufhörst und auf "Senden" drückst. Wenn etwas unklar ist, einfach nochmal nachfragen. Sollte ich merken, dass wenig eigene Motivation besteht, Probleme zu verstehen oder selbst an der Lösung (mit) zu arbeiten, werde ich meine Motivation dementsprechend anpassen. Bitte auch keine Mails im Messenger-Stil. Die E-Mail ruhig mal 5 Minuten länger offen lassen und noch nicht direkt losschicken statt nacheinander 3 Mails, die jeweils nur einen Punkt umfasst. Die Antwort kommt deswegen nicht schneller (im Gegenteil, solche Mails bleiben eher länger liegen). Bitte verwende Satzzeichen und diese idealerweise auch an der richtigen Stelle (siehe [[wpde:Plenk|Plenk]]). Bitte auch selbst kritisch denken. Jeder macht Fehler und je nach Tageszeit werden sie bei mir auch mal mehr. Versteh es einfach als Kompetenzübung und beachte den Haftungsausschluss. =Werbung= Was vielen auf dieser Homepage dank Werbeblocker wahrscheinlich gar nicht auffällt: Es gibt keine Werbung. Ich hab zwar schon ein-/zweimal mit dem Gedanken gespielt, welche zu schalten aber komme dann immer wieder auf einen Punkt zurück: ich/wir machen das aus Spaß und Werbung hat (zumindest bei mir) einen kommerziellen Charakter oder zumindest schalen Beigeschmack – das möchte ich nicht. Auch habe ich mittlerweile schon ein paar Mailanfragen für Kooperationen und „Sponsored Posts“ bekommen, auf die ich – obwohl es natürlich verlockend ist – nicht eingehe. Zum Einen aus den oben genannten Gründen, zum Anderen möchte ich das Ganze hier möglichst ehrlich und authentisch (mit allen Vor- und Nachteilen) halten. Heißt: ich vertrete meine Meinung und nicht die anderer. Wenn hier im Blog, im Wiki oder sonstwo steht, dass etwas toll oder bescheiden ist, handelt es sich um eine persönliche Meinung. Die muss zwar nicht unbedingt richtig sein, aber es wurde zumindest nichts durch finanzielle Mittel beeinflusst. =Spenden= Obwohl das Internet (auch oder vor allem im privaten Bereich - siehe "Influencer") immer kommerzieller wird, wird man beim genaueren Blick ins Blog oder ins Wiki bzw. hier im Impressum sehen: ich möchte hier ausdrücklich kein Geld verdienen. Als hier im Impressum der Hinweis für Agenturen bereits war und sie trotzdem geschrieben haben, habe ich immer wieder geantwortet, dass sie das Geld auch einem sinnvollen gemeinnützigen Verein spenden sollen. Passiert ist natürlich nichts. Auch wenn es wahrscheinlich nur verschwendete Zeit war: ich wollte zumindest nicht nichts tun. Die hier vorgestellten Basteleien, die Pflege der Homepage und alles andere darum ist Hobby - und per definitionem schließt das ein Einkommen aus. Nicht umsonst heißt es: "mit größtmöglichem Aufwand den kleinstmöglichen Nutzen erzielen". Da mich diejenigen, denen ich “übrige“ Leiterkarten der verschiedenen Basteleien hier geschickt habe fragten, wohin sie mir Geld überweisen sollen, konnte ich nur antworten, dass ich aufgrund verschiedener Umstände gar nicht annehmen darf (und will). Um jedoch trotzdem das 'schlechte Gewissen' zu beruhigen, entstand folgende Idee: Wer von mir etwas bekommt (oder was ich mache gut findet) ist aufgerufen einen Betrag - nach eigenem Ermessen - an eine sinnvolle gemeinnützige Organisation spenden. So entsteht eine ″Win-Win-Win-Situation″: Ich werde meine Leiterkarten los, der Empfänger bekommt etwas zu Basteln und gemeinsam wird auch noch etwas Gutes getan. Wer mir also etwas Gutes tun möchte: Spende an eine Organisation, die du für gut hältst, der Betrag ist mir egal, ich freue mich aber über (gerne auch anonymisierte) Spendenquittungen. Wenn du möchtest, kannst du auch auf q.hobbyelektronik.org/spenden verweisen. '''Bei den Leiterkarten möchte ich jedoch darauf hinweisen: Die fallen nicht vom Baum, auch kostet der Versand etwas.''' Wichtig ist mir, dass das Geld auch ankommt und möglichst wenig in der Verwaltung hängen bleibt. Wer überhaupt keine Idee hat wohin: Lokale (Kinder-)Hospize und (Kinder-)Palliativ-Stationen sind stark auf Spenden angewiesen. Wenn es technisch sein soll: Kleinere Hackerspaces oder Gruppen wie Freifunk sind auf Spenden angewiesen. Absolut richtig zu spenden ist natürlich nicht einfach, dennoch bitte ich folgendes in Erwägung zu ziehen´: * Einen etwas schalen Beigeschmack hatte ich bei einer Spende an die dt. Krеbshilfe, die offenbar nicht wenig ihrer Einnahmen in Werbung und „Bettelbriefe“ steckt. * Fragwürdig halte ich ebenfalls ΡeTA, die eher durch Desinformation und mittlerweile auch Verleumdungsvorwürfe auffallen. * Bitte von Spenden an die kath. Kіrche und deren Organisationen in meinem Namen Abstand nehmen, solange sie: ** Ihre Finanzen nicht offenlegen ** Sich stark durch den Staat finanzieren lassen, aber trotzdem das Sagen haben (und dabei durchaus diskriminieren) ** Missbrauch tolerieren, billigen, vertuschen, nicht vernünftig aufarbeiten und sogar Strafverfolgung behindern ** Frauen nicht gleichberechtigen ** ... (Ich weiß: "aber, aber, aber..." - bitte nicht falsch verstehen: jeder darf und soll glauben was möchte, für mich sind Glaube und Κirche unterschiedliche Dinge.) =Nutzung von Inhalten= Wie in der Fußzeile zu sehen ist, unterliegen die Inhalte (sofern nicht anders angegeben) der Creative Commons-Lizenz [https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de BY-NC-SA 3.0]. Inhalte dürfen also ausdrücklich unter Namensnennung (vorzugsweise einem Link auf hobbyelektronik.org) für nichtkommerzielle Angebote verwendet werden. Für die Verwendung in kommerziellen Angeboten ist vorab bitte Kontakt (siehe oben) mit dem Seitenbetreiber aufzunehmen. Eine direkte Einbindung der Ressourcen dieser Website (zum Beispiel Bilder mit <code>src="//hobbyelektronik.org/..."</code>) auf Fremdseiten ist nicht erwünscht und sollte daher unterlassen werden. Ausnahmen hierfür sind: RSS-Feeds oder persönliche Aggregatoren sowie Suchmaschinen, deren Zweck das Auffinden von Inhalten ist. =Haftungsausschluss= ==Haftung für Inhalte== Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Die auf dieser Homepage bereitgestellten Inhalte wurden nach bestem Wissen und Gewissen erarbeitet und recherchiert. Trotzdem können Fehler nicht ausgeschlossen werden und daher keine Garantie auf Vollständigkeit und Korrektheit der bereitgestellten Informationen gegeben. Ferner wird keine Haftung für direkte und indirekte Schäden übernommen, die durch das Lesen oder das Auf- bzw. Nachbauen von Schaltungen und Aufbauten oder deren Inbetriebnahme bzw. das Nachstellen von beschriebenen Vorgehensweisen oder Techniken entstehen können. Dies gilt insbesondere für Schaltungen oder Anordnungen, die für den Menschen gefährliche Einflussgrößen wie zum Beispiel elektrischen Strom, Spannungen, Chemikalien oder Strahlungen erfordern oder hervorbringen. ==Haftung für Links== Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. ==Urheberrecht== Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind ohne weitere Genehmigung nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen. ==Lizenz== Alle vom Seitenbetreiber erstellten Inhalte unterliegen, soweit nicht anders gekennzeichnet, der Lizenz Creative Commons - [https://creativecommons.org/licenses/by-nc-sa/3.0/de/ Attribution-NonCommercial-ShareAlike 3.0] (kurz: CC BY-NC-SA 3.0). =Datenschutzerklärung= ==Datenschutz== Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Auf die Einbindung von Ressourcen von Drittservern wird bewusst vermieden und soweit wie möglich unterbunden, kann jedoch technisch nicht vollständig ausgeschlossen werden. Diese Homepage deren Dienste werden durch die "Hetzner Online GmbH" gehostet. Der Betreiber dieser Homepage hat keinen Einfluss auf Technik, Datenschutz und Datenintegrität des Hosters. ==Cookies== Die Internetseiten verwenden teilweise so genannte Cookies. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Sie dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch gelöscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen. Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein. ==Server-Log-Files== Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log Files, die Ihr Browser automatisch an uns übermittelt. Dies sind: * IP-Adresse * Username für Authentifikation * Uhrzeit der Serveranfrage * Methode der Anfrage (GET/POST/...) * Abgerufener Pfad und Query * Protokollversion * Statuscode des Servers * Ausgelieferte Dateigröße * Referrer URL * User Agent des verwendeten Browsers Diese Daten sind nicht bestimmten Personen zuordenbar. Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen. Wir behalten uns vor, diese Daten nachträglich zu prüfen, wenn uns konkrete Anhaltspunkte für eine rechtswidrige Nutzung bekannt werden. Ferner werden durch den Hoster Statistiken erstellt, die in aller Regel nur für diesen und den Betreiber der Website einsehbar sind. Die erfassten Daten werden - je nach verfügbarem Speicherplatz - zeitlich unbegrenzt gespeichert. ==Kommentarfunktion== Einige Teile dieser Homepage ermöglichen das Hinzufügen von Kommentaren durch Besucher. Die dort vertretenen Aussagen und Meinungen entsprechen nicht zwangsläufig denen des Betreibers der Seite. Zum Zwecke der Vermeidung von Werbung, Spam und niedrigem Niveau findet eine Moderation der Kommentare statt. Sofern nötig behält sich der Betreiber das Recht vor, Wörter oder Textpassagen (unter Kenntlichmachung) zu entfernen. Zu diesem Zweck werden, neben den über das Formular eingegebene Daten, folgende Informationen dauerhaft gespeichert: * IP-Adresse * Datum und Uhrzeit * Browsertyp/Browserversion ==E-Mails== E-Mails werden sowohl auf dem Mailserver als auch auf den Clients der Nutzer dieser Seite vorgehalten. Dies kann sowohl für ein- als auch ausgehende Nachrichten zeitlich begrenzt aber auch unbegrenzt erfolgen. Die Regelaufbewahrungszeit auf dem Server beträgt, sofern abgerufen, 30 Tage. Auf den Mailclients können die Nachrichten zeitlich unbegrenzt gespeichert, archiviert und in Backups gesichert werden. Durch den Kommunikationspartner angegebene Daten können ebenfalls dauerhaft und in schweigender Zustimmung in Adressbüchern abgelegt werden. Eine Datenhaltung in "Cloud-Diensten" wird ausdrücklich vermieden, kann aber nicht vollständig ausgeschlossen werden. Sollte eine dauerhafte Speicherung von Nachrichten nicht gewünscht sein, sind diese jeweils durch den Text "**NOARCHIVE**" im Betreff zu kennzeichnen. Ein späterer Bezug auf diese Nachrichten ist dann verständlicherweise nicht mehr möglich. Durch einen Befall durch Schadsoftware auf einen der genutzten Endgeräten kann es zum Versand von unerwünschten Nachrichten kommen. Bei Kenntniserlangung werden umgehend Abstellmaßnahmen eingeleitet und - soweit technisch möglich - die Empfänger dieser Nachrichten gewarnt. ==Verschlüsselung== Diese Homepage wird vorzugsweise über HTTPS/TLS ausgeliefert. Ein Downgrade auf HTTP ist möglich, kann aber zu Darstellungsfehlern führen. Der Mailtransport über TLS wird angeboten, zusätzlich ist eine Mailverschlüsselung auf Basis von GPG (siehe oben) möglich. Quelle e-recht24.de (angepasst) 02a09fcc7590f270dd1bd09955f1fb9001499c84 Datei:Vbuspi 1.3 pers.jpg 6 830 1864 2023-08-25T20:19:27Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Datei:Vbuspi 1.3 top.jpg 6 831 1865 2023-08-25T20:19:27Z Chris 2 Hochgeladen mit [[mw:Special:MyLanguage/Extension:SimpleBatchUpload|SimpleBatchUpload]] wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 VBus-Decoder/Adapter für den Raspberry Pi v1.3 0 715 1866 1838 2023-08-25T20:22:36Z Chris 2 Bilder hinzugefügt wikitext text/x-wiki [[Bild:Vbuspi 1.3 pers.jpg|thumb|Aufgebauter Leiterkarte (v1.3)]] ''Dies ist ein Unterartikel von [[VBus-Decoder]]. Auf der Hauptseite gibt es weitere Informationen zum Thema.'' =Motivation= Who's perfect? Beim [[VBus-Decoder/Adapter_für_den_Raspberry_Pi|VBus-Adapter für den Raspberry Pi]] (und auch dem [[VBus-Decoder/Adapter_Nano|Nano]]) gibt es ein paar Unzulänglichkeiten, die jeweils ein Makeover der Leiterkarte erfordern. Da die Beliebtheit des Raspberry Pis deutlich größer als ein Arghduino für solche Anwendungen ist, gibt es hierfür zuerst (oder überhaupt) eine neue Version. Konkret handelt es sich um folgende Probleme, die mit der neuen Version behoben werden sollen: * Keine gestapelten Bauteile mehr * Hinreichend Eingangskapazität für mehr Zuverlässigkeit * Größere Bauteile zur einfacheren Bestückung * Rückkanal, um den Regler aktiv abfragen und parametrieren zu können =Änderungen= Aus dem MLCC-Kondensator wurde ein Elektrolyt, aktuell 100 µF, lässt sich bei Bedarf aber noch ein bisschen vergrößern. Dieser wird nun über einen Widerstand am Gleichrichter angebunden um den Ladestrom (und dadurch die Spannungseinbrüche auf dem Bus) zu verkleinern. Ob die Kombination aus 470 Ohm und 100 Mikrofarad gut ist, muss sich noch zeigen. Beim Spannungsregler ist der 3,3 V-Typ gekommen um zu bleiben. Dieser bietet neben dem etwas niedrigeren Preis den Vorteil, dass er auf der Eingangsseite einen größeren "Headroom" hat. Die Neudimensionierung der Spannungsteiler basiert auf den Berechnungen von [[Adapter_für_den_Raspberry_Pi_v1.2#Die Enttäuschung - Teil 2| Version 1.2b]]. Als Bestückoption gibt es nun auch einen Jumper, mit dem die Versorgung des Komparators ausgewählt werden kann - sollten die Referenzspannungen nach dem 3,3 V-Regler doch zu knapp werden, kann die Eingangsspannung des LDO verwendet werden. Offen ist natürlich, ob der zu erwartende Ripple in die Suppe spuckt. Die diskreten Bauteile sind nun alle im 0805-Package, dadurch wurden weite Teile des Layouts umgeworfen. Wer möchte, kann natürlich auch welche im 0603-Package (oder mit ein bisschen Wollen sollte auch 1206 gehen) auf die Footprints packen. Gänzlich neu ist der Rückkanal, die Dimensionierung dessen Bauteile erfolgte mit dem feuchten Finger in den Wind gehalten. Es ist eigentlich nichts besonderes zu erwarten, bei Bedarf kann allerdings einfach mit den Bauteilen gespielt werden. Die Änderungen kommen allerdings mit ein paar Kompromissen: * Die Leiterkarte wurde ein bisschen größer * Die Power-LED für den VBus ist rausgefallen (kein Platz, unnötiger Verbraucher) * Bei der Nutzung des Rückkanals ist... ** die Leiterkarte auf dem Pi Zero nur mit "Überhang" verwendbar ** keine galvanische Trennung möglich <gallery> Vbuspi_1.3_assy_sch.png | Schaltplan Vbuspi_1.3_assy_brd.png | Layout Vbuspi_1.3_top.jpg | aufgebaute Leiterkarte </gallery> =BOM= <tabs> <tab name="Optoisoliert"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 3 || R2, R6, R8 || 15k || R0805 || RND 0805 1 15K |- | 1 || X1 || 1751248 || 1751248 || AKL 059-02 |- | 2 || R9, R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 1 || OK1 || 6N136 || DIL08 || 6N 136 |- | 1 || R1 || 15k || R0805 || RND 0805 1 15K |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 1 || Q1 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_opto_sch.png | Bestückungsplan für optoisolierte Variante </gallery> </tab> <tab name="Direkt"> {| class="wikitable" ! Menge || Referenzen || Wert || Package || Reichelt Bestellcode |- | 3 || R10, R11, R15 || 0 || R1206 || RND 0805 1 0 |- | 2 || C2, C8 || 100n || C0805 || X7R-G0805 100N |- | 1 || C6 || 100p || C0805 || NPO-G0805 100P |- | 1 || C5 || 100u/16V || PANASONIC_D || VF 100/16 K-D |- | 5 || R2, R6, R8, R13, R14 || 15k || R0805 || RND 0805 1 15K |- | 1 || X3 || 1751248 || 1751248 || AKL 059-02 |- | 1 || R28 || 1k || R0805 || RND 0805 1 1,0K |- | 1 || C4 || 1n || C0805 || NPO-G0805 1,0N |- | 2 || R4, R7 || 2k2 || R0805 || RND 0805 1 2,2K |- | 1 || R12 || 330 || R0805 || RND 0805 1 330 |- | 2 || R3, R5 || 4k7 || R0805 || RND 0805 1 4,7K |- | 1 || C3 || 4u7 || C0805 || KEM X5R0805 4,7U |- | 3 || D1, D2, D5 || BAV99 || SOT23 || BAV 99 NXP |- | 3 || Q1, Q2, Q3 || BSS138 || SOT23 || BSS 138 SMD |- | 1 || IC4 || LM393D || SO08 || LM 393 D SMD |- | 1 || D3 || P6SMB 15A || SMBJ || P6SMB 15A SMD |- | 1 || X2 || RPI_UART+_CONDENSED || RPI_UNIV+_UART || RND 205-00655 |- | 1 || IC1 || TS5205CX533 || SOT23-5 || TS 5205 CX533 |- | 1 || LED1 || or || CHIP-LED0805 || LED EL 0603 OR |} <gallery> Vbuspi_1.3_assy_direct_sch.png | Bestückungsplan für unisolierte Variante </gallery> </tab> </tabs> =Hinweise= * '''Bitte nur die Bauteile bestücken, die in der BOM für die jeweilige Variante angegeben sind. Mehr hilft nicht mehr, sondern kann zu Fehlfunktionen führen.''' * R14 in der Direktvariante sollte nicht bestückt werden oder zumindest in Pull-up-Konfiguration umgebaut werden. Sonst kann (und wird) es passieren, dass der VBus bei nicht angeschlossenem Tx dauerhaft kurzgeschlossen wird. (Danke an Heiko für den Hinweis!) * R1 sollte einen Wert ab ca. 12k haben, damit der Low-Pegel auch wirklich 0 erreicht. * Aktuell ist nur die optoisolierte Version getestet * selbst bei "nur" 1,2 mm dickem FR4 würde ich nicht empfehlen, die Leiterkarte an den perforierten Kanten zu brechen. Besser sägen oder mit einer Trennscheibe arbeiten. * Nicht vergessen, JMP1 zu bestücken oder zumindest die entsprechende Lötbrücke zu setzen. =Leiterkarten= Es gibt noch unbestückte Leiterkärtchen. Wer eine will, kann sich gerne bei mir melden. =Downloads= * [[Datei:Vbuspi_1.3.zip]] EAGLE-Dateien Adapter v1.3 für den Raspberry Pi [[Kategorie:Raspberry Pi]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 85e934ad6b04db17e646b3e22dd88c6ef393e724 VBus-Decoder 0 120 1867 1837 2023-08-25T20:24:11Z Chris 2 /* Adapter für den Raspberry Pi */ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokoll erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Dies kann entweder mit Hilfe des Handbuchs in Erfahrung gebracht werden (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung vorhanden) oder durch Messung ermittelt werden: An den VBus-Klemmen sollte eine (zappelnde) Spannung von ca. 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/#/vsf Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg|Unbestückte v1.0-Leiterkarte Vbuspi 1.1 assy zero.jpg|Bestückte v1.1-Leiterkarte auf einem Raspberry Pi Zero W Vbuspi_1.3_pers.jpg | v1.3-Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> ===Versionen=== * [[VBus-Decoder/Adapter für den Raspberry Pi v1.0|Version 1.0/1.1]]: Der erste Versuch - "never trust a x.0" * [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2|Version 1.2]]: Besser, aber noch nicht gut * '''[[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]]: Die beste Version, die man aktuell haben kann ;)''' ==[[VBus-Decoder/Adapter für den ESP8266|Adapter für den ESP8266]]== Noch etwas kleiner als für den Raspberry Pi: Ein Adapter mit ESP8266-Modulen. <gallery> vbusesp_top.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] Oliver hat basierend auf dem Code von Nicki eine Schnittstelle zur [https://www.volkszaehler.org/ Volkszähler]-Middleware gebaut: <pre> Der Code nutzt die Resol-Decoder-Lib von Nicki, die ist auch mit dabei. In der config.py stellt man die Adresse der Middleware in seinem Netzwerk, sowie die UUID der Kanäle ein, damit man die Daten referenzieren kann. (Zum Test kann man auch simulierte Daten nutzen, oder die Ausgabe in ein File schreiben lassen) </pre> * [[Datei:Vbus_volkszaehler.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] d2546caa14ba2b78e1186202e433f6d3db6c6476 1869 1867 2023-08-25T21:09:56Z Chris 2 /* Adapter für den Raspberry Pi */ wikitext text/x-wiki [[Bild:Vbus regler.jpg|thumb|Das Corpus Delicti]] Bei der Solaranlage meiner Eltern übernimmt ein Viessmann Vitosolic 200 die Regelung. Nach kurzer Recherche stellte sich heraus, dass es sich um eine etwas angepasste Version des [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de RESOL DeltaSol® M] handelt. Statt der RS-232-Schnittstelle hat das Teil einen Anschluss für den Viessmann-eigenen KM-Bus, zu dem mir keinerlei Informationen bekannt sind. Beim VBus sieht es deutlich besser aus. In der [http://www.mikrocontroller.net/topic/96431 Diskussion] auf Mikrocontroller.net bin ich auf den Beitrag von [http://www.mikrocontroller.net/topic/96431#1231974 Daniel Wippermann] gestoßen, woraufhin ich an die angegebene Adresse eine E-Mail geschickt habe. Keine zweieinhalb Stunden später habe ich die Dokumentation (inklusive der Erlaubnis zur Veröffentlichung, siehe Download) zum Protokoll erhalten. Irgendwann nach der Erstveröffentlichung dieses Artikels entstand eine deutlich erweiterte Dokumentation auf den [https://danielwippermann.github.io/resol-vbus/vbus-specification.html Github-Seiten von Daniel Wippermann]. Nicht nur das, sondern auch eine Implementierung des Protokolls in Javascript. =Hardware-Schnittstelle= [[Bild:Resol sch.png|thumb|Wo Rx und Tx ist, muss erraten werden ;)]] Bei dem VBus handelt es sich um eine bidirektionale halbduplex Zweidrahtschnittstelle, die - entgegen mancher Meinungen - überhaupt keine Ähnlichkeiten mit RS-485 hat. '''Bei ein paar Reglern scheint Resol eine RS-485-Schnittstelle mit VBus-Protokoll zu verwenden, die mit den hier vorgestellten Schaltungen nicht kompatibel ist. Bitte vor dem Nachbau der Hardware prüfen, um welches System es sich handelt. Dies kann entweder mit Hilfe des Handbuchs in Erfahrung gebracht werden (Angabe der Spannung und Strom, bei RS-485 ist üblicherweise keine Stromversorgung vorhanden) oder durch Messung ermittelt werden: An den VBus-Klemmen sollte eine (zappelnde) Spannung von ca. 8 V anliegen.''' Der Master (Regel-Einheit) versorgt den Bus mit etwa 8,2 V und 35 mA (S. 4 in der Doku). Die Daten werden durch Spannungsabsenkung auf dem Bus übertragen. Mit der Schaltung auf Seite 5 des PDFs kann auf dem Bus sowohl gelesen, als auch geschrieben werden. Im Bild rechts meine Interpretation der Schaltung (in der noch die Abblockkondensatoren fehlen). Über die Buchse links kann man sich mit UART (nicht RS-232!) mit 9600 Baud, 8 Datenbits, 1 Stoppbit ohne Parität mit dem Master unterhalten. Der in meiner Schaltung verwendete FET für die bidirektionale Kommunikation ist übrigens ein BS170; wobei der Typ nicht kritisch ist, solange er den Bus kurzschließen kann, ohne dabei in Rauch aufzugehen. =Protokoll= Das Protokoll des VBus ist in seiner Version 1.0 ziemlich gut handzuhaben. Folgendes Daten habe ich zum Testen verwendet: <code> <span class="he0"><span class="hb1">0xAA</span>, <span class="hb2">0x10, 0x00</span>, <span class="hb3">0x21, 0x73</span>, <span class="hb4">0x10</span>, <span class="hb5">0x00, 0x01</span>, <span class="hb6">0x12</span>, <span class="hb7">0x38</span></span>, <br /> 0x5E, 0x04, 0x5E, 0x01, 0x05, 0x39, <br /> 0x45, 0x01, 0x38, 0x22, 0x04, 0x5B, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x6C, 0x01, 0x38, 0x22, 0x05, 0x33, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x38, 0x22, 0x38, 0x22, 0x05, 0x46, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x38, 0x0F, 0x00, 0x00, 0x01, 0x37, <br /> 0x47, 0x00, 0x00, 0x00, 0x00, 0x38, <br /> 0x64, 0x64, 0x00, 0x00, 0x00, 0x37, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, <br /> 0x00, 0x00, 0x43, 0x00, 0x00, 0x3C, <br /> 0x00, 0x00, 0x02, 0x00, 0x00, 0x7D, <br /> 0x01, 0x03, 0x60, 0x02, 0x04, 0x15, <br /> 0x02, 0x00, 0x00, 0x00, 0x00, 0x7D, <br /> </code> Zu allererst wird ein <span class="he0">10 Byte langer Kopf</span> gesendet, der mit einem eindeutigen <span class="hb1">Sync-Wort (0xAA)</span> beginnt. Eindeutig heißt: An keiner anderen Stelle im Protokoll wird dieses Zeichen verwendet (bzw. das MSB belegt). Man kann sich also zu jedem beliebigen Zeitpunkt in den Bus einklinken! Gefolgt vom Sync-Wort kommen <span class="hb2">Ziel-</span> und <span class="hb3">Quelladresse</span> (<span class="hb2">0x0010</span> <= <span class="hb3">0x7321</span>), <span class="hb4">die Protokollversion (0x10)</span>, der <span class="hb5">ausgeführte Befehl (0x0100)</span> und die Anzahl der danach folgenden <span class="hb6">Nutzdatenframes (0x12)</span>. Abschließend wird eine <span class="hb7">Prüfsumme (0x38)</span> der zuvor gesendeten Daten übertragen. Im Anschluss an den Header wird die im Header angegebene <span class="hb6">Anzahl an Datenframes</span> mit je 6 Byte Länge geschickt (Auszug von oben): <code> <span class="hb1">0x5E, 0x04, 0x5E, 0x01</span>, <span class="hb2">0x05</span>, <span class="hb3">0x39</span>, </code> Die ersten 4 enthalten <span class="hb1">Nutzdaten</span>, im 5. wird ein <span class="hb2">Septett</span> geschickt und abschließend erfolgt wieder eine <span class="hb3">Prüfsumme</span>. Das Septett ist eine Ergänzung der zuvor gesendeten Nutzdaten. Da, wie oben erwähnt, das MSB nur im Sync-Wort vorkommen darf, ist es für die folgende Daten kein verboten - dieses findet sich jeweils in diesem zusätzlichen Byte. Die Prüfsumme der einzelnen Nachrichtenteile wird mittels CRC8 berechnet. Das ist auch schon das Gröbste. Mit Protokollversion 2.0 und 3.0 habe ich mich noch nicht auseinandergesetzt, da diese zum Erfassen der Messwerte nicht benötigt werden. ==Adressen== Wie in vielen Bussystemen verwendet auch der VBus Pakete für die Nachrichten. Zu den Informationen in der PDF-Spezifikation sei an der Stelle auch auf die [https://danielwippermann.github.io/resol-vbus/#/vsf Paketbeschreibung] verwiesen. Die für den bei uns eingesetzten Regler lautet die Adresse 0x7321 (Vitosolic 200 [Regler]), die für das Logging relevanten Daten gehen an 0x0010 und werden in der Dokumentation lediglich als DFA beschrieben. Dabei handelt es sich nicht um eine komische Umschreibung für einen Broadcast, sondern um die Daten für ein zusätzliches Gerät - der Datenfernanzeige. An diese sendet der Regler alle von ihm gemessenen Werte. Neben der Regler-Identität hat der Vitosolic 200 noch die Identitäten WMZ1 und WM2 (Wärmemengenzähler). =Hardware= Im Laufe der Zeit haben sich mehrere Schaltungen ergeben. Um diesen Artikel übersichtlich zu halten, wurden die verschiedenen Varianten auf Unterseiten aufgeteilt: (Die Links zu den Unterseiten sind befinden sich jeweils in den Überschriften) ==[[VBus-Decoder/Adapter für RS-232|Adapter für RS-232]]== Wenn man noch einen PC oder Adapter hat der RS-232 spricht, kann sich dieser Hardware bedienen. Der Zugriff ist nur lesend möglich und es gibt keine galvanische Trennung zwischen Bus und DTE. <gallery> Bild:Vbus_rxo_brd.png|thumb|Layout der PC-Hardware </gallery> ==[[VBus-Decoder/Adapter Nano|Adapter Nano]]== Die vermutlich universellste Variante - schön klein, galvanische Trennung und funktioniert auf der Empfängerseite ab 3,3 V. <gallery> resol_nano_0.1_assy.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter für den Raspberry Pi|Adapter für den Raspberry Pi]]== Wer Geräte ins Netzwerk bringen will, hat meistens auch einen Einplatinencomputer der Raspberry Pi Foudation auf der Liste. <gallery> Vbuspi 1.0 bare.jpg | Unbestückte v1.0-Leiterkarte Vbuspi 1.1 assy zero.jpg | Bestückte v1.1-Leiterkarte auf einem Raspberry Pi Zero W Vbuspi 1.3 pers.jpg | v1.3-Bestückte Leiterkarte auf einem Raspberry Pi Zero W </gallery> ===Versionen=== * [[VBus-Decoder/Adapter für den Raspberry Pi v1.0|Version 1.0/1.1]]: Der erste Versuch - "never trust a x.0" * [[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.2|Version 1.2]]: Besser, aber noch nicht gut * '''[[VBus-Decoder/Adapter_für_den_Raspberry_Pi_v1.3|Version 1.3]]: Die beste Version, die man aktuell haben kann ;)''' ==[[VBus-Decoder/Adapter für den ESP8266|Adapter für den ESP8266]]== Noch etwas kleiner als für den Raspberry Pi: Ein Adapter mit ESP8266-Modulen. <gallery> vbusesp_top.jpg|Bestückte Leiterkarte </gallery> ==[[VBus-Decoder/Adapter_Nano#Troubleshooting|Troubleshooting]]== Für die Schaltung des Adapter Nano gibt es eine Troubleshooting-Anleitung, die in Teilen auch für die 5 V-Version der Raspberry-Pi-Variante gültig ist. =[[VBus-Decoder/FAQ|FAQ]]= (bitte auf die Überschrift klicken) =Software= ==[[VBus-Decoder/AVR8-Software|AVR8]]== Zur Datenauswertung und für einfache, zusätzliche, Regelaufgaben (wie zum Beispiel Deaktivieren der Heizung, wenn die Solaranlage den Speicher belädt) - oder um die Anlage ins Internet of Things zu bekommen sind Mikrocontroller sehr geeignete Komponenten. Eine Implementierung für die [[VBus-Decoder/AVR8-Software|AVR8-Plattform]] findet sich auf der entsprechenden Unterseite. ==Python== Nicki hat sich die Arbeit gemacht und einen Code zum Auswerten der Nachrichten in Python portiert. Ich hatte selbst noch keine gute Gelegenheit, ihn zu testen - daher ohne Garantie, Gewährleistung oder Support: * [[Datei:VBus-Python.zip]] Oliver hat basierend auf dem Code von Nicki eine Schnittstelle zur [https://www.volkszaehler.org/ Volkszähler]-Middleware gebaut: <pre> Der Code nutzt die Resol-Decoder-Lib von Nicki, die ist auch mit dabei. In der config.py stellt man die Adresse der Middleware in seinem Netzwerk, sowie die UUID der Kanäle ein, damit man die Daten referenzieren kann. (Zum Test kann man auch simulierte Daten nutzen, oder die Ausgabe in ein File schreiben lassen) </pre> * [[Datei:Vbus_volkszaehler.zip]] ==Protokoll-Analysator== Da es mehrere Anfragen zur Untersuchung des Protokolls gab, habe ich vor einer Weile einen kleinen Protokollanalysator zusammengestrickt. Dieser unterstützt aktuell Protokollversion 1.0 und ist als "gefährliche Beta" anzusehen: [https://hobbyelektronik.org/tools/vbus-analyzer/ Resol Protocol Analyzer] =Downloads= * [[Datei:VBus-Protokollspezifikation.pdf]] Stand: 20.04.2009 * (Die Downloads für die Hardware befindet sich auf der jeweiligen Unterseite) '''An dieser Stelle noch einmal vielen Dank an Resol für die Bereitstellung der Informationen und die Erlaubnis, diese hier weiter zu verteilen!''' =Weblinks= * [http://www.mikrocontroller.net/topic/96431 Diskussion auf Mikrocontroller.net] (gleicher Link wie in der Einleitung) * [http://www.resol.de RESOL - Elektronische Regelungen GmbH] * [http://www.resol.de/index/produktdetail/kategorie/1/id/9/sprache/de DeltaSol® M] Regler, der dem Viessmann Vitosolic 200 "alt" in ziemlich genau entspricht * [https://danielwippermann.github.io/resol-vbus Github-Seiten von Daniel Wippermann] [[Kategorie:AVR]] [[Kategorie:Energieerfassung]] [[Kategorie:Solaranlage]] [[Kategorie:VBus]] 0a75fc28cb048d4c5750b26acfe3ff787d336964